WebAssembly 与 AI 推理:游戏内 NPC 智能的端侧部署新路径 On-Device AI Inference for Game NPCs
别急着把 LLM 当成 NPC 的全部——端侧 AI 推理真正能改变的,是那 16 毫秒里玩家能感知到的反应速度
为什么端侧推理是 NPC 智能的第一块基石
玩家推开酒馆的门,柜台后的 NPC 抬头看了他一眼。就这一眼,藏了三个问题:他什么时候抬头(感知)、他为什么要抬头(推理)、抬头之后用什么表情(表演)。
老派做法是行为树写死三个分支——玩家第二次进门就开始腻。AI 时代大家第一反应是调云端大模型——但你算过延迟没有?一帧是 16.7 毫秒,云端 API 一次往返是 300 到 2000 毫秒,差了整整两个数量级。中间那 1.9 秒的空档,你要么让 NPC 卡在原地罚站,要么用硬编码动画来糊弄,然后玩家感叹一句“这个 AI NPC 好僵硬”。
这就是端侧推理存在的理由。WebAssembly 在这条线上的位置很微妙:它不是让 AI“更好”的东西,它是让 AI 更快、更便宜、更贴身的载具——把模型塞进浏览器,让推理发生在玩家本机的 CPU 和内存里,边际成本归零,隐私不出本机,延迟低到可以逐帧生成行为。
但说句实话,这个话题的坑比馅饼多。过去两年我见过太多团队一上来就喊“Wasm 跑 LLM 做 AI NPC”,最后模型 8GB、加载三分钟、玩家连门都没进就关页面。端侧推理真正能救的,不是“让 NPC 会聊天”,而是“让 NPC 的反应感追逐帧率”。这篇就聊聊这个落点,以及到底该怎么设计。
第一层:延迟是第一性原理——端侧推理到底“推”什么
先把玩家视角摆出来。所谓“AI NPC 好玩”,玩家的体感并不来自模型参数量,而是来自反应的可预期性与不可预期性的配比。NPC 每次进门反应一样,玩家嫌死板;每次反应完全随机,玩家觉得他脑子有病。恰到好处的“他好像真的注意到了我,但没完全按我想的来”,才是沉浸。
这个体感背后是一套推理预算。玩家能容忍的反应延迟,跟场景强相关:
| 场景 | 玩家可感知延迟阈值 | 典型触发 |
|---|---|---|
| 格斗/回避类的实时反应 | ≤ 50ms | 玩家出拳、NPC 闪避 |
| 视线追踪/转头/注视 | ≤ 100ms | NPC 目光跟随玩家 |
| 对话分支选择 | ≤ 400ms | 玩家开口后的第一句回应 |
| 行为决策(走位/攻击/逃离) | ≤ 800ms | 战斗状态切换 |
| 剧情对话、情感反应 | ≤ 3s(云端也行) | 长线对话、剧情推进 |
看清楚这个表你就明白了:真正需要端侧的,全在前三档;后面两档交给云端大模型完全没问题。很多团队做 AI NPC 做砸了,就是因为把云端方案往最前档硬塞——用 800ms 往返去驱动一个需要 50ms 反应的动作,玩家只会觉得这 NPC“灵魂出窍”。
反过来,端侧的极限也不浪漫。一台中端手机浏览器里,Wasm 单线程跑神经网络,能拿到的算力大概在几百 MFLOPS 量级——这意味着一秒能跑的推理次数是有限的。你想每帧 60 次推理、每次都上百万参数的大网络?洗洗睡。所以端侧推理的第一条设计律是:不是让模型更强,是让需要推理的频率和单次开销,刚好贴住可感知延迟的那条线。
再往下挖一层,端侧推理相对云端的优势其实是四象限的,不只是延迟:
| 维度 | 云端 API | Wasm 端侧 |
|---|---|---|
| 响应延迟 | 300ms - 2000ms,受网络抖动 | 1ms - 50ms,稳定 |
| 边际成本 | 按调用量线性上涨,DAU 上去就烧钱 | 一次性分发成本,用户越多越划算 |
| 隐私 | 玩家输入(语音/文字)要出设备 | 数据不出本机 |
| 离线可用性 | 网络断了就瘫 | 加载完就能一直跑 |
| 模型自由度 | 可上几百亿参数大模型 | 撑死上千万参数的小模型 |
看懂最后一行——这是所有端侧 AI 落地的分水岭。云端能上 GPT-4 级,端侧只有几千万参数的预算。所以端侧该干什么、不该干什么,其实是被参数预算写死的。
真实案例:Lichess 浏览器端的 Stockfish NNUE。这个案例我特别爱讲,因为它把“端侧推理”这件事剥得干干净净。国际象棋引擎 Stockfish 从 2020 年开始换用 NNUE(Efficiently Updatable Neural Network,高效可更新神经网络)做局面评估——这就是一个真实的神经网络推理。Lichess 平台上大量对局是跑在玩家浏览器的 Wasm 版 Stockfish 里的,模型文件带上权重大概 30-40MB,一次评估里遇到 NNUE 前向计算的耗时被压缩到毫秒量级,配合搜索算法每秒能评估几十万个局面。玩家能感知到什么?走子前的思考时间稳定在 1 秒上下,不会像云端 AI 那样偶尔站在那儿三秒不动。
它的设计意图值得细品:Stockfish 从不指望 NNUE 一步给出“正确走法”,NNUE 只负责给局面打分(价值评估),真正的走子由搜索树做剪枝。这就是端侧推理的正确姿势——让推理做“估值”,让传统逻辑做“决策”。你在游戏里也一样:让推理器给 NPC 当前的情绪状态、威胁感、兴趣度打分,行为树再根据这些分数选分支。模型的输出不直接驱动动作,而是调制动作——这是端侧推理在游戏里最稳的用法。
收益是明显的:Lichess 靠这套把“AI 陪练”做成了平台的核心功能,无限次对局、无网络也能玩、零 API 成本。代价也很清楚:模型是被高度裁剪过的(只够评估棋局这一个任务),一旦想让它“理解吐槽”“聊个天”立刻超预算。端侧推理的天花板,就是你敢不敢把任务切窄。
第二层:模型、内存与量化的物理约束
好,任务切窄了,模型炼好了,导出成 ONNX 或 TF.js 格式,接下来就是 Wasm 这一层要面对的现实:模型怎么进到浏览器里、怎么跑、跑的时候吃多少内存。
先讲部署路径。今天主流的端侧推理方案大致是三条:
| 方案 | 模型格式 | Wasm 角色 | 适合场景 |
|---|---|---|---|
| TensorFlow.js + Wasm 后端 | TF.js Graph / Layers 模型 | 推理核用 Wasm + SIMD + XNNPACK 加速 | 视觉/姿态类现成模型,快速起原型 |
| ONNX Runtime Web | ONNX | Wasm 执行后端跑 CPU 推理 | PyTorch 转出的自定义模型,跨平台一致性 |
| 自有推理引擎编译成 Wasm | 自己定义 | 整个推理引擎都是 Wasm | 极致定制、模型极小、想榨干 SIMD |
三条路的共同点,是模型权重最终要以一个字节数组的形式进入 Wasm 的线性内存,然后推理核从这块内存里读数据、算矩阵乘。核心的性能瓶颈往往不是计算本身,而是内存布局和数据搬运。这是新手最容易翻车的地方——模型跑得慢,你会发现一半时间花在把输入数据从 JS 堆拷进 Wasm 内存里。
怎么办?零拷贝。Z 世代的说法是“别把球传三次再投篮”。Wasm 和 JS 共享一个 ArrayBuffer 视图时,可以让输入数据一步到位地写到 Wasm 的堆上,输出直接读。ONNX Runtime Web 和 TF.js 都支持“张量直接绑定到预分配内存”,用好这一条,能砍掉 30%-60% 的额外开销。这件事听起来工程化,但它直接影响体验:一个 30ms 的推理如果花 20ms 在搬运数据,你砍掉的 12ms,就是 NPC 从“反应有点钝”变成“反应像人”的那道坎。
接着说量化——这是端侧推理的生命线。模型权重从 FP32 降到 FP16、再到 INT8,体积能压到原来的 1/2 到 1/4,速度往往能翻倍,但精度会掉。掉多少、掉在哪儿,非常考设计。
| 精度 | 模型体积倍数 | 速度(相对 FP32) | 典型精度损失 | 游戏里的表现 |
|---|---|---|---|---|
| FP32 | 1x | 1x | 基准 | 最稳,但体积大 |
| FP16 | ~0.5x | 1.3-1.8x | <1% | 几乎无感,推荐首选 |
| INT8(动态量化) | ~0.25x | 2-4x | 1%-5% | 多数行为决策可用,情感类模型慎用 |
| INT4 及以下 | ~0.125x | 3-5x | 5%-15%+ | 只适合特别宽容的打分模型 |
“INT8 丢 1%-5% 精度而已,能有啥事?”——这种想法我见过太多人翻车。游戏 NPC 的行为模型有个特点:它对输出的细微漂移极其敏感。一个本该选“后退”的概率从 0.72 掉到 0.55,模型可能就切到“犹豫”分支,玩家体感的 NPC 性格就从“谨慎”突变到“迟钝”。所以我的原则是:决策模型先拿 FP16 保命,情感/表演类模型拿 INT8 试,INT4 只用在纯打分(比如威胁度评估、路径成本估计)这种粗糙任务上。量化不只是一种压缩手段,它本质上是一个设计决策——你在用模型的精确度,换运行时的确定性。
真实案例:TensorFlow.js 的 WebAssembly 后端 + MoveNet/PoseNet 姿态模型,在浏览器体感游戏里的落地。这条线是端侧推理在游戏里最有实战感的样本。体感类浏览器小游戏(跳舞、动作打卡、AR 投球这类)需要摄像头实时识别人体关键点,模型文件 MoveNet 单姿态版本大约 5-13MB,通过 TF.js 的 Wasm 后端(带 SIMD 和 XNNPACK 加速)在浏览器里跑,手机端可以稳定跑到每秒 20-30 次推理。给你一个量级感:一次推理 ≈ 15-25ms,加上摄像头解帧和前处理,整条管线能压进 33ms 一帧的预算。玩家在摄像头前挥手,屏幕上小人跟着动,延迟在 100ms 以内——注意这个数字,它恰好落在“可感知延迟阈值”表里的第 2 档上。
它踩过的坑值得咱们抄作业。第一坑:SIMD 检测。老版 Firefox、部分 iOS Safari 没有 Wasm SIMD,回退到标量版本性能掉一半,游戏直接从“跟手”变“拖影”,所以必须做能力检测和降级路径(降模型精度而不是降帧率)。第二坑:模型体积和首屏加载。一个 10MB 模型加上 Wasm 运行时本体,首屏加载能到十几秒,玩家早跑了。他们的解法是模型分片加载 + 缓存在 IndexedDB,第二次进入秒开——模型加载时间必须当成包体优化的一部分来算,这条与专题里讲包体压缩的那篇([10])是同一个战场。第三坑最隐蔽:摄像头、音频、渲染线程会抢 CPU,你的推理预算是浮动的,得给它设一个“最低可用帧率”护栏,宁可推理频率降到每秒 10 次,也不能让整个游戏卡成 PPT。
第三层:把推理结果翻译成“可感知的行为”——调度与后处理
模型能跑起来只是及格。真正决定玩家觉得“这 NPC 有灵魂”的,是推理结果怎么被调度、怎么被翻译成动作。这一层几乎全是游戏策划的活,不是算法工程师的活。
我们先定一个基础架构:推理器不掌管行为,只调制行为。行为树、状态机还是那套老骨架,负责保底逻辑和程序化动作;推理器在旁边做“风味层”,给每个决策分支一个连续的评分或参数。举例:NPC 面对玩家时有四类基础反应(无视、注视、靠近、对话),推理器每秒算一次玩家对它的“吸引力评分”(基于距离、持械状态、当前情绪、过去交互历史),这个评分映射成行为树的权重参数。这样即便模型输出有小噪点,最终玩家看到的行为依然连续可信。
调度频率是这一层的核心参数。几种常见策略:
| 策略 | 推理频率 | 适合场景 | 代价 |
|---|---|---|---|
| 每帧推理 | 60Hz | 战斗反应、视线跟踪 | 算力爆炸,慎用 |
| 固定低频率 | 2-10Hz | 常规行为决策 | 反应迟钝,但可控 |
| 事件驱动 | 触发时算 | 玩家进门、开枪、受伤 | 突发流量,需排队 |
| 分层混合 | 感知层高频、决策层低频 | 绝大多数 3A 或独立游戏 | 架构复杂 |
我强烈推荐“分层混合”。感知层(比如视线方向、威胁判定)跑得勤一点,每帧或每两帧一次,用极简模型;决策层(选哪个行为分支)跑得慢一点,每 200-500ms 一次,用相对复杂的模型;剧情表演层(表情、台词)事件驱动,几秒一次。这样既保证反应感,又把算力预算摊平。这套“分层调度”跟传统游戏里动画系统的 LOD 是一个思路——重要的事情多算,不重要的事情少算。
接下来是容易被忽略但极其关键的“抖动抑制”。推理模型每次输出的评分都有一点点随机波动,如果你直接把它映射到行为参数上,NPC 就会抽风——一秒钟在“犹豫”和“前进”之间切换三次,玩家会以为他犯癫痫。抑制抖动有两个工具:
迟滞和平滑。迟滞就是给切换设置不同的阈值——从“注视”切到“靠近”门槛是 0.7,从“靠近”切回“注视”门槛要掉到 0.5 才切,人为制造一个缓冲区。平滑就是对连续参数做滑动平均,三五帧的窗口就足够,既能消抖又不会让反应显得迟钝。这两个东西本质上是“把 AI 判断包在一个可信的时间滤波里”,和相机跟随里用的那套柔化手感是同一门手艺。设计得当,玩家甚至感觉不到推理在变化,只会觉得这 NPC 反应“有分寸”。
还有一个更深的坑:推理输入该用什么特征?很多团队懒,直接把玩家坐标、距离、血量往模型里一塞,然后抱怨模型没学会“人味”。其实关键不在模型,在特征选择。真正让 NPC 显得“懂人”的输入不是位置,而是关系状态:玩家和 NPC 的距离变化速率(是不是在逼近)、玩家装备变化(掏枪了没有)、历史交互记忆(上次对话是不是不欢而散)、环境上下文(旁边有没有其他 NPC 在看)。这些特征维度不多,一二十维就够,但每一个都需要策划先想清楚“这影响 NPC 什么情绪”。这不是算法问题,这是系统设计问题——你得先想明白 NPC 决策模型里应该刻画哪些“动机变量”,模型才有机会学到它们。
案例对照:Whispers from the Star 的云端 LLM 路线,为什么会撞在这个问题上。2025 年蔡浩宇团队 Anuttacon 出品的这款 AI 驱动叙事游戏,口碑两极分化得很典型。它的核心卖点是全 LLM 驱动的对话 NPC,智能感拉满——但玩家吐得最多的恰恰是“反应慢半拍”“我要等好几秒”。为什么?因为对话式 LLM 天生是云端推理,一次往返几百毫秒到几秒不等,而叙事游戏里玩家的每一次输入都期待即时的表情反馈。它不是做错了,是模型任务没切窄——把“叙事推进”和“即时表演”绑在了同一次云端调用里。Epic 的做法就聪明得多:把两者拆开,表演层用本地逻辑 + 轻量模型兜底,叙事层才交给云端。这正是端侧推理在设计上的价值定位——它不抢云端的活,它承包云端够不着的那 16 毫秒。
第四层:Wasm 和 WebGPU 的分工——算力管线的边界
聊到这儿必须直接面对一个现实:WebAssembly 不是浏览器里唯一能算 AI 的东西,WebGPU 也能,而且跑大矩阵运算远比 Wasm 快。很多文章把这个当成“二选一”,实际上它们是两种完全不同的兵器。
Wasm 的问题是纯 CPU 算力有限,矩阵乘法是串行或者有限并行的,跑一个几十层的大网络就是慢性死亡。WebGPU 的问题是它是异步的、初始化有开销、控制流能力弱,更别说 WebGPU 的浏览器兼容性在 2025 年仍未完全铺开(尤其 iOS Safari 的支持路径还在追)。它们的分工本质上是控制流 vs 数据流:Wasm 擅长逻辑、条件判断、非线性处理;WebGPU 擅长批量并行的矩阵乘和卷积。
所以正确的管线形态通常是三者协作,而不是谁替代谁:
| 管线阶段 | 执行者 | 职责 |
|---|---|---|
| 输入采集与前处理 | Wasm | 从游戏世界读数据、归一化、拼特征张量 |
| 大矩阵计算(权重计算) | WebGPU | 矩阵乘、卷积、激活函数 |
| 后处理与调度 | Wasm | softmax、采样、抖动抑制、结果映射到行为树参数 |
| 渲染 | WebGL/WebGPU | 场景渲染,与推理并行 |
WebLLM(MLC 团队的项目)把这个分工用到了极致——它把大语言模型的矩阵运算全压在 WebGPU 上,让浏览器也能跑 7B 级模型。但它根本不是 Wasm 推理的胜利故事:WebLLM 能跑起来,恰恰是因为它避开了 Wasm 的计算瓶颈,把 Wasm 只用在控制流和调度上。这个对比非常关键,因为行业里经常有人拿它来吹“Wasm 能跑大模型”——技术上跑起来了,但每次推理要几百毫秒到秒级,跟游戏中需要的 1-3ms 端侧反应是两个世界。
游戏开发者的策略因此很清晰:模型参数量决定你走哪条路。
| 模型规模 | 推理主战场 | Wasm 的角色 | 典型用途 |
|---|---|---|---|
| < 100 万参数 | Wasm CPU 单线程 | 全部推理 | 情绪打分、视线判定、路径成本 |
| 100 万 - 1000 万 | Wasm + SIMD | 全部推理,SIMD 加速 | 语音唤醒、简单姿态、面部表情识别 |
| 1000 万 - 1 亿 | Wasm + WebGPU 混合 | 前后处理、控制流 | Medium 级视觉模型、轻量 TTS |
| > 1 亿参数 | WebGPU 或云端 | 调度、输入输出 | 语音合成、小 LLM、图像生成 |
这里有一个独立开发者最容易忽视的量化判断:如果你的玩法不需要每帧推理,别硬追求端侧。一个每 30 秒才调用一次的 NPC“内心独白”,云端 API 一秒往返完全无感;一个需要每帧检测玩家姿态的体感游戏,云端延迟就是死刑。先决定玩法的时间粒度,再决定算力路线——这是系统设计的老规矩,只不过换到了 AI 这个新战场。
最后补充一点被低估的能力:Wasm 的“控制流优势”在游戏 AI 里特别值钱。真实游戏里的 NPC 决策不是纯前馈——它有优先级打断、有模态切换、有“如果玩家距离近到 1 米内就直接进入警戒状态”这种硬规则。这些逻辑放 WebGPU shader 里写是灾难,放 Wasm 里就是一行条件判断。所以哪怕未来 WebGPU 推理成为主流,Wasm 那一层也不会消失,它会从“推理计算者”退化成“AI 行为调度者”——角色换了,位置还在。
参数化设计工具:一张表管住端侧 AI 的预算
把前面所有讨论收束成一张配置表。我按“独立团队做中度玩法”的口径给的建议区间,硬核项目自己往上调:
| 参数 | 建议区间 | 调大/调小的代价 |
|---|---|---|
| 端侧推理模型体积 | 独立游戏 ≤ 5MB;中度游戏 ≤ 20MB | 调大→包体膨胀、首屏加载时长上升、玩家流失 |
| 模型量化精度 | 决策层 FP16;表演层 INT8;纯打分模型 INT8/INT4 | 掉得越狠行为越“反常”,玩家会敏锐察觉 |
| 单次推理耗时预算 | 感知层 1-3ms;决策层 5-15ms;表演层不限 | 超预算就会挤占渲染帧率 |
| 决策层推理频率 | 2-10Hz(100-500ms 一次) | 调高→算力爆、NPC 行为抽风;调低→反应迟钝 |
| 感知层推理频率 | 15-30Hz | 低于 15Hz 玩家能感到“目光滞后” |
| 输入特征维度 | 32-256 维 | 太低→模型学不会;太高→过拟合、加载慢 |
| 输出动作/参数维度 | 4-16 维 | 多于 16 维通常不必要,反而难调试 |
| 切换迟滞阈值 | 0.1-0.2 的分差 | 太小→行为抖;太大→反应僵 |
| 平滑窗口 | 3-5 帧 | 同上,需和迟滞配合调 |
| WebGPU 分流阈值 | 模型 > 1000 万参数考虑上 WebGPU | 过早引入→兼容性风险;过晚→性能瓶颈 |
| 模型加载分片大小 | 2-4MB / 片,缓存在 IndexedDB | 过大→首屏等待过长;过小→请求过多 |
用法上给个粗手感的顺序:先定玩法时间粒度(是否需要逐帧反应),再定推理预算,再选模型规模,最后才做量化。顺序反过来——先把模型练得很大再回头压——最常见的结局是压到行为崩坏、剧情线全乱,只能推倒重来。我自己也翻过这个车,一个心情管理系统模型练得挺漂亮,量化到 INT8 之后 NPC 在大街上不停切换“恐惧”和“好奇”两种状态,玩家反馈说“这人是不是有精神分裂”。后来把表演层换回 FP16 才救回来。
初级速览 / 进阶深潜
初级用户速览(3 步走):第一步,先回答“你的玩法真的需要端侧推理吗?”如果只是让 NPC 说几句有反应的话,云端 API 完全够用,别为难自己。第二步,如果确实需要即时反应(体感、视线、战斗),先用 TensorFlow.js + Wasm 后端 + 现成模型(PoseNet、MoveNet、简单的情绪分类器)跑通一个最小闭环,感受一下推理频率和延迟的真实体感,再决定要不要往自定义模型上走。第三步,把推理结果做成行为树的“参数调制”,不要直接驱动动作——这一条能救你 80% 的“AI 抽风”问题。
进阶用户深潜(4 步走):第一步,用 ONNX Runtime Web 做部署,把 PyTorch 训练流程直通到浏览器端,用 FP16 起步,并做好 SIMD 检测和平滑降级路径。第二步,把推理拆成感知层/决策层/表演层三段,各自用不同频率和不同精度,做好时间预算分配。第三步,在 Wasm 和 WebGPU 之间切分管线——模型上千万参数以后,矩阵运算走 WebGPU,前后处理和调度留 Wasm,用异步流水线避免阻塞渲染。第四步,把模型加载当作包体优化来做(参照 [10] 那篇里的分片加载和 Brotli 压缩),用 IndexedDB 缓存二次加载;同时接入性能打点,监控单次推理的真实耗时和你纸面上的理论耗时差多少——这个差值通常比模型本身还值得优化。
争议与常见坑
坑一:以为 Wasm 能跑 LLM 做全对话 NPC。能跑,但你分不清“能跑起来”和“能玩下去”。上百亿参数的模型在浏览器 Wasm 里要么跑不动,要么秒级延迟,玩家早关页面了。真正的 AI NPC 叙事是云端大模型 + 端侧表演层的混合结构,不是全端侧。
坑二:把首屏加载不当回事。一个 15MB 模型加运行时,在 4G 网络上首屏能拖到 20 秒。这个数字对独立游戏是致命的——绝大多数玩家在 8 秒内就跑了。模型一定要分片、一定要缓存。
坑三:量化掉精度后行为崩坏。这是最隐蔽的坑,因为它不会报错,只会让 NPC 行为变得“不太对”。一定要做量化前后行为一致性对比,别拿指标数字当验收。用一小批“行为快照”(同样的输入序列看输出分支),比你盯 loss 曲线有用得多。
坑四:直接用推理输出驱动动作。这是新手最容易犯的错。模型输出有噪点、有散热、有时序不稳定,直接驱动动作一定抽风。永远给行为树留“骨架”,AI 只做“皮肤”。
坑五:以为云端便宜所以不用端侧。单次调用几毛钱听起来很便宜,但一个 10 万 DAU 的游戏,每人每天 20 次 AI 交互,一天就是几百万次调用,一年算下来够请两个程序。端侧推理的边际成本是零,规模越大越香。
坑六:忽视 WebGPU 兼容性。2025 年了,WebGPU 在桌面 Chrome/Edge 上很稳,但移动端 Safari 和部分 Android WebView 仍在追加支持中,做跨平台游戏一定要留 WebGL/Wasm 的回退路径。赌单一渲染后端是拿用户群做赌注。
FAQ
Q1:Wasm 到底能不能跑大语言模型?我想让 NPC 完全自由对话。
技术上能跑小参数版本(10 亿参数以内的模型在 Wasm + 量化后确实能转起来),但游戏里能用的时间预算是每 100-500ms 出一次结果,这个速度下的大模型输出质量会掉到“人工智障”级别。想要自由对话,走云端 + 端侧轻量表演层混合路线;想要稳定低延迟反应,走小模型端侧。别指望一个方案通吃。
Q2:TensorFlow.js、ONNX Runtime Web 和自研推理引擎怎么选?
原型阶段用 TensorFlow.js,生态现成、上手最快;产品阶段如果主流训练链路是 PyTorch,用 ONNX Runtime Web 迁得更顺;追求极致包体和性能、或者模型结构特别特殊(比如自定义的小型图网络),才考虑自研编译到 Wasm。绝大多数游戏不需要走第三条。
Q3:为什么我用 Tf.js 的 WebGL 后端跑得挺快,切到 Wasm 反而更慢?
因为 WebGL 后端把矩阵运算搬到了 GPU,而 Wasm 是纯 CPU 计算。小模型在 WebGL 上往往赢,大模型才在 Wasm + SIMD 上找回优势。别迷信“Wasm 一定快”,测一遍才知道——这也呼应了专题里 [27] 那篇“Wasm 性能神话的破解”。
Q4:手机浏览器能撑住端侧推理吗?
撑得住轻量级(几百万参数、FP16、单次几毫秒),撑不住重负载。关键判断是“每帧推理次数”和“模型规模”,手机上单帧推理预算设 5-10ms 比较安全,超过 15ms 就会明显拖累帧率。还要注意老设备的 Wasm SIMD 支持度,做好降级。
Q5:如果我游戏根本不需要实时反应,云端 API 不是更划算吗?
那当然云端更划算,而且模型能力上限高得多。端侧推理不是“政治正确”,是“场景匹配”。什么时候端侧有理?延迟敏感 + 高频调用 + 隐私敏感 + 离线可用,四项里踩中两项以上再考虑端侧。