从行走到连招:一次 MotionBricks 接入实验

发布于

2026年10月30日

更新于

2026年10月30日

Engine

从行走到连招:一次 MotionBricks 接入实验的反复排查

把 MotionBricks 接进引擎后,我先修左右脚步幅,再修待机站姿,最后补上攻击和三连击。自动检查陆续通过,实际操作依然让我失望。最难的部分逐渐变成:怎样确认一次修改真正改善了角色控制?

2026 年 10 月,我在自己的 HitagiEngine 中做了这次实验,希望角色根据操作和环境生成动作,减少为起步、转向、停步和跳跃手工组织过渡的工作。我一度撤回演示接入,后来又恢复代码,继续验证目标帧、步态相位和动作库的想法。

以下记录截至 10 月 31 日的排查过程。如果你也打算把生成模型接到玩家控制器上,相位和待机锚点这两轮实验,能说明条件构造与后处理怎样改变最终动作;最后的攻击实验则留下了尚未解决的操控问题。

第一阶段:先让模型输出驱动自己的角色

最初要打通的是从键盘操作到角色画面的完整路径。模型输出使用 SOMA 骨架,项目里使用的角色是 Sour Miku,两者之间还需要重定向。

实验使用 Windows Release 构建,通过 TensorRT 运行 FP32 SOMA 模型。

应用先把“继续往左走”“停下来”等键盘操作转换成目标和约束,交给模型。生成的动作经过骨架转换和接触修正,最终呈现在角色上。

这里先明确“预设”的含义:公开示例把参考姿态、目标放置和运行时参数组织成方便试用的配置。选择预设后,应用从中取出具体姿态并构造约束,再交给模型。模型实际消费的是姿态和运动约束;预设名称只属于应用层。

以本次使用的公开 SOMA ONNX 接口为例,一次调用包含以下内容:

输入描述的内容
近期姿态最近四帧的身体状态,为动作衔接提供上下文
目标姿态最多四帧目标条件,包含关节位置与旋转
根运动约束位置、朝向、水平速度、转向速度和高度
有效性掩码哪些姿态和根运动条件生效
允许的 token 数可选择的生成长度范围

这些输入最终编码为数值张量。详细字段以固定版本 SOMA 模型卡的输入表为准。

因此,行走、蹲走或坐下的差别,通过具体的身体姿态和运动约束表达。参考姿态可以从动作片段中提取,也可以手工制作。论文的 Smart Locomotion 将风格关键帧与操控产生的目标组合;Smart Object 则把交互关键帧绑定到物体,随物体的位置与朝向放置。公开预设提供了这套接口的使用示例。论文 §6

这也决定了后面的排错方向:需要检查预设最终构造出了什么条件,以及这些条件是否符合当前操作与环境。

图 1:本次接入的流程。蓝色区域是生成模型;历史反馈来自运行时播放的 SOMA 姿态,初音网格位于重定向和接触修正之后。

这条路径跑通后,角色能够响应移动操作。持续操作时,后半段却出现了像半蹲着走路的姿态。问题可能出在目标构造、生成姿态或重定向/IK,这次实验先从画面上最明显的腿部和接触处理查起。

第二阶段:从半蹲姿态查到接触修正

第一段录像之后,我的反馈是:后半段有一种突然半蹲着走路的感觉。

图 2:手动录像约 7.9 秒的姿态。结合下方视频的前后运动,可以观察动作是否突兀。

完整手动录像 A:12.184 秒。如果 Markdown 阅读器不支持内嵌视频,可以直接打开链接。建议先看完整片段,再回看约 7~9 秒。

检查膝盖和鞋底接触时,接入代码暴露出一个问题:落脚锚点滞留后,求解器会通过下压骨盆去满足它。这次修正限制了骨盆下压,并放松不可达的锚点。

接触处理的修正改善了部分表现。要解释剩下的异常,还需要看模型究竟收到了什么条件,以及输出在重定向前是什么样子。于是我提出:把模型真正收到的输入画出来。

第三阶段:把输入画出来,发现移动条件在减速

这一轮的重点是核对操作意图和模型条件是否一致。仅看最终角色,很难判断矛盾发生在哪一层。

第二段录像增加了诊断显示。黄色骨架代表应用提供的未来条件,蓝色骨架代表当前 SOMA 姿态;粉色和绿色分别显示原始输出与端点修正后的根轨迹。看清每一层的数据,成为这次排查的转折点。

图 3:手动录像 B,约 2.6 秒,第 589 次规划。黄色条件接近直立,位置仍在行进方向前方。正文插图已裁掉编辑器界面;黄色和蓝色骨架保留在场景中供对照。

完整手动录像 B:5.939 秒。建议观察约 2.3~3.3 秒,再与前后正常移动部分比较。

录像之外,录制功能还保存了操作输入和模型条件。重新核对这些数据,可以看到一个具体矛盾:操作仍持续要求向左移动,但未来条件前两帧之间的水平根速度,在几次规划中降到了约 0.058、0.032 和 0.024 m/s。

图 4:横轴为该次规划首次被录制采样观察到的时间。蓝线由未来条件前两帧的水平根位置差乘以 30 Hz 得到;下方显示水平操作输入。

当时的简化实现循环采样完整的 walk 动作片段,把减速、停步部分也取了进来,随后又将姿态平移到前方。结果是:位置在要求“去前面”,连续条件帧却传达了“速度已经很低”。

针对这个矛盾,控制器把风格姿态与期望速度分开,并按论文的 Smart Locomotion 思路调整目标构造,让位置、姿态与速度约束协调。

调整后,持续移动输入下的条件速度通过了检查。这一轮终于有了可以复现和核对的输入错误。

继续操作时,我又发现角色停下来以后也会出问题。

第四阶段:修正持续待机时的姿态变化

目标看起来仍然垂手,角色却逐渐把手收在腹前,双脚和身体的姿态也偏离了预期。

图 5:黄色目标与蓝色当前 SOMA 的手臂已经不同,姿态差异出现在重定向到初音之前。

图 6:待机反馈中的双脚与身体姿态。漂移时长和速度需要连续记录才能测量。

当时的待机逻辑一直生成、提前重规划,再把生成结果作为下一轮历史。参考官方运行时,控制器改为先完成进入待机的过渡,再循环播放待机片段,等新操作到来后退出。

图 7:待机状态逻辑示意。修正后,生成的过渡结束便进入稳定的循环状态。

调整状态机之后,两分钟模拟回归中,骨盆、双手腕、双脚踝在相同待机周期相位的位置差为零,旋转差在浮点误差量级。这解决了该循环随时间变化的问题。

图 8:修正后版本的自动回归第 7199 帧。图 5、图 6 来自更早版本的手动反馈。

待机循环稳定后,脚部画面仍有另一种差异:源骨架的脚和角色的鞋对不上。

第五阶段:源骨架的脚,为什么对不上角色的鞋

在观察角色时,我又注意到源骨架脚端与实际鞋部的位置差异。它直接影响了我对落点和支撑姿态的判断。

图 9:蓝线为 SOMA 源骨架,网格为重定向后的初音。二者在髋宽、腿长和脚型上的差异,需要在重定向中处理。

这套重定向主要传递旋转,同时保留角色自己的骨长,再做高跟鞋接触修正。鞋底着地之后,还需要验证步宽、支撑关系和落点是否保留了源动作的意图。

因此,后来又补上了实际腿骨和鞋底的诊断线,用来对照重定向前后的支撑关系。

回归中的鞋底高度、膝盖弯曲方向和根节点连续性检查通过。这些指标分别覆盖了以下性质:

检查已验证的性质还需评估的质量
鞋底高度接近地面被测接触点符合高度阈值足部落点、步宽和滑步质量
膝盖弯曲方向IK 解落在允许的弯曲方向姿态自然、转向流畅
根节点位移位置连续性符合阈值操控响应符合预期
交互序列完成状态机走到了结束接触准确、交互位置合理

这张表也说明了当时验证的边界:鞋底贴地和根节点连续,都无法回答动作是否符合操作意图。接入环境交互后,这个差别更加明显。

第六阶段:从公开预设走向环境交互,停在了固定入口

接入公开预设后,演示能够避障、跳跃、坐下和起身。我希望自由控制角色靠近物体,由当前位置、朝向和环境决定可执行的动作。

第一版会把角色放到测试起点,按空格执行整条序列。体验更接近动作演示。随后,控制器取消传送,增加了接近和朝向检查:玩家走近地面箭头,满足条件后按空格触发。

图 10:环境交互自动回归第 300 帧,角色完成了预设入口对应的坐下序列。

回归中,预设序列能够执行完成。实际操作时,我仍然需要走到指定入口。期望中的体验要求系统根据接近方向、当前位置和环境,动态确定哪里可以起跳、越过什么、落在哪里。环境交互层还需要补上这些决策。

图 11:上方为本次实现,下方为待补齐的环境决策与目标生成流程。

固定入口来自这次的实现。 目标放置、环境查询、接触与状态选择仍需要自己搭建。到这里,后续工作已经涉及一整套环境交互系统;脚部质量和更广泛的操控验证也还在等待处理。

第七阶段:恢复实验,保留目标四帧内部的运动

第一次撤回后,我重新追问模型输入:四帧从哪里来,间隔多大,位置如何设置?当时的实现会去掉每帧自己的水平根位置,再按指令速度逐帧放置。参考动作里的组内位移因此被改写,身体姿态与根运动可能出现矛盾。

我提出把第一帧作为锚点,后续三帧保持相对关系,再录制同样的模拟输入做对照。

恢复代码后,实验比较了两种条件构造。旧方式按指令速度重建每帧根位置;新方式给四帧施加同一个平移与旋转,保留参考片段内部的位移和姿态变化。四帧仍按 30 Hz 连续采样,相邻间隔约 33.3 毫秒。

图 12:同一组目标的四帧共享一个刚体变换。窗口内部的相对运动保留,窗口之间的选择和推进仍由应用负责。

四帧共享变换后,参考片段内部的运动保住了。我又从侧面观察十秒连续行走,角色仍然一脚迈得大、一脚迈得小,看起来像受伤了。接下来要查的是:每次送进去的目标,处在步态周期的什么位置?

第八阶段:重复同一相位,让左右脚迈出了不同的幅度

采样被分成网络原始位置、预测旋转重建的骨架、端点修正后的姿态和最终角色。偏差在重定向之前已经存在,因此,仅修改初音的重定向和 IK 无法消除它。排查重点回到了输入条件。

这一轮完成了 26 个受控对照。关闭端点修正、改变重规划间隔、减少目标帧数,都未消除原来的偏差。

更有区分力的实验是固定目标根轨迹、根高度和髋部朝向,只更换目标身体姿态的相位。左右偏差的方向随之反转。保持根运动条件不变,身体姿态仍能改变偏向,这让目标相位成为下一步要验证的因素。

原实现持续重复同一组参考相位,同时以约 2.3 m/s 放置内部速度约 1.152 m/s 的目标组。后来让目标沿完整参考周期推进,并统一速度,两侧摆动明显接近。

30 秒直行条件左脚最大前伸均值右脚最大前伸均值
原条件43.9 cm32.2 cm
只统一速度23.1 cm34.1 cm
只推进相位48.1 cm44.1 cm
相位推进与速度统一36.1 cm35.8 cm

统计排除了起始两秒,按完整步态周期计算脚踝相对骨盆的最大前伸。这是受控实验中的 SOMA 指标;它覆盖直线行走,交互中的起停、变速和转向还要另外验证。

正式修正加入了基于历史脚膝姿态与速度的相位估计。一次 30 秒中性行走回归中,最终初音两侧前伸差约 0.79 cm,原实现同口径约 10.89 cm。之后又把相位对齐扩展到走跑混合和六种行走风格。

在这组实验里,相位推进与速度统一一起改善了两侧摆动。只改速度时,偏差甚至换了方向。以后遇到类似的不对称,我会先查看参考窗口怎样推进,再决定是否调整脚部求解器。

第九阶段:姿态停止漂移,双脚却停在了错误位置

行走改善以后,操控仍暴露出新问题。跑步切回走路时,未来目标直接回到角色面前;长时间放置后,双腿又显得不对。我也要求 WASD 跟随相机方向。

速度输入加入加减速限制,Walk/Jog/Run 按同一只脚的相位原点对齐,再混合参考姿态。相机的水平前向和右向负责把 WASD 转成世界方向。

待机则查到了另一类错误:进入新的循环姿态时,鞋底仍然使用移动或转向期间的旧锚点。源姿态已经变了,IK 继续把脚拉向原来的位置,结果可以长期稳定地保持错误站姿。转向案例中,源动作两脚前后差约 4 cm,最终角色曾达到约 21.5 cm。

修正是在切入待机时更新支撑目标,用 0.35 秒完成锚点交接,然后保持稳定。

四组各两分钟的回归中,重复姿态漂移为零,站姿误差约 5.65–6.80 mm。

回头看,早先的待机测试只比较同一周期相位的姿态有没有变化。双脚一直被拉在旧锚点上,也能通过这种检查。加入相对目标站姿的误差后,测试才覆盖了这次实际看到的错位。

这些修正花费了不少精力。我仍想知道,动作库能否让更具体的行为变得可控,于是继续尝试攻击、跳跃和翻滚。

第十阶段:动作片段送进模型后,挥拳仍像摆姿势

我的设想是:动作库提供参考,状态机根据操作选取目标帧,MotionBricks 生成角色实际执行的动作。这样可以尝试出拳、前跳、跳跃攻击和翻滚,并进一步组合这些行为。

参考动作选用 Quaternius 的 CC0 Universal Animation Library Standard,在 Blender 中重定向到 SOMA。出拳使用 Cross 和 Jab,跳跃由起跳、腾空、落地片段组合,跳跃攻击叠加上身出拳。资源页面

第一版采用混合实现:核心段直接播放片段,只有收招输入四帧目标让模型生成。它通过了连续动作检查,却偏离了这轮实验的目标。我明确要求把动作片段作为模型输入。

随后,核心段也改走模型:每个阶段从片段提取连续四帧,与最近四帧实际执行历史一起送入 MotionBricks;角色执行解码后的结果,再做已有端点校正、重定向和 IK。

输入核验确认了目标窗口与源片段的一致性。首轮四动作测试执行了 16 次窗口推理、267 帧模型输出,状态机也能正常结束。

实际操作时,我的反馈却是:挥拳看起来像短促地摆出一个 pose,动作非常不连续,也无法接出组合。原来的第一组出拳目标取第 12–15 帧,这几帧已接近伸拳保持;之后的窗口很快转向收手。同时,动作期间再次按 F 会被忽略。

这次失败说明,模型收到正确的四帧,仍然需要应用组织完整的运动意图、时间安排和输入响应。 前一版“160 次动作全部完成”的结果属于核心段直接播放的版本;它只能证明那套混合状态机完成了测试,不能用来评价后来全生成版本的动作质量。

第十一阶段:补上拳路和三连击,实际体验仍未达标

这时需要解决两件事:一拳要有准备、伸拳、回收和收势;连续按键要在合适的窗口接下一拳。仅增加几个结束状态,仍然会留下节奏问题。

出拳窗口改为从参考第 4、8、18、26 帧开始,每组依然包含连续四帧。新的 F 按下事件进入单槽缓冲,在衔接点接出 Cross → Jab → Cross,三拳之间保留生成历史和世界放置,最后统一收招。长按 F 触发一次。

又一次画面复查发现,一拳被拖到了两秒多。本次运行时将每个窗口约束为六个 token,产生 17 个新动作步,按 30 Hz 执行约 0.57 秒。把各段依次执行,时长就累加起来了。

后来给准备、出拳、回收、收势分配 6/4/6/8 个实际动作步,对模型输出做时间重采样。单拳约 0.8 秒,三连击约 1.87 秒。这是应用层新增的时序处理,执行速度已经不同于模型原始输出;下一轮输入历史取自实际执行后的姿态。

图 13:最终连招版本的自动录像,按从左到右、从上到下排列,约为 1.2、1.33、1.6、1.87、2.13、2.67 秒。全部为原始场景裁剪,保留黄色目标与蓝色当前骨架。离散截帧展示姿态变化,连续性需要观看视频。

三连击与长按单拳的模拟录像:16 秒。约 1~2.87 秒执行三连击,约 11.67~12.47 秒执行长按 F 触发的单拳。画面已经裁掉编辑器,只保留场景;播放速度对应这版实际执行时序。

自动测试确认了三连击中间没有进入待机,三拳和之后的单拳共触发四个攻击事件。手腕轨迹与逐帧画面能看到伸拳、回收和换手。跳跃及走跑回归也通过了。

我再次实际操作后的反馈仍然很明确:这套控制依然不好用。 输入缓冲和动作计数证明了组合机制工作,拳路、衔接和操控质感仍然达不到我的期待。时间压缩把一拳缩短了,也增加了对执行速度和历史反馈的处理,动作质量依然需要验证。

到这里,控制器已经包含参考动作、阶段目标和连招缓冲。我仍无法放心把它用于玩家的高频攻击操作。

最后的复盘:继续修下去,需要承担什么成本

几轮实验确实解决了条件速度、目标相位和支撑交接中的具体错误。继续加入动作库和连招以后,满意的高频操控体验依然没有出现。我把这些实现结果与论文和公开模型说明放在一起,重新评估继续投入的收益。

论文披露的限制

论文 §8.1 承认稀有动作覆盖不足、物理上不合理的动作和跨体型重定向困难;其中对运行时重定向质量的评价也相当直接。论文 §8.1

公开 SOMA 模型卡进一步说明:场景几何由应用处理,模型消费姿态与运动约束;分布外约束可能产生非预期运动;精度和运行时差异可能随历史反馈累积。发布的 ONNX 文件仍缺少完整的端到端质量基准。固定版本的 SOMA 模型卡

目标姿态、位置、速度约束、时长范围和重规划策略都可以调整,生成之后也可以增加 IK 或回退逻辑。

我关心的是另一件事:能否只修某一个局部表现,而不用重新担心其他情况下的行为?

当生成过程参与决定中间运动时,改一个条件可能同时改变时序、姿态和路径。修复一处表现之后,需要重新检查更多行为组合。在这次接入中,这种验证成本成为继续使用它的主要障碍。

X 上的使用反馈

2026 年 10 月 28 日,@tvitzer 在 X 上反馈:MotionBricks 用到自己的角色骨架后,效果不如预期,他个人更倾向于从自己拍摄的视频提取动作。这与本次骨架接入体验接近,具体原因仍需复现材料才能判断。原帖

同一讨论的主帖来自 @rehan_shei,展示批处理和动态群集的潜力。这是另一个有价值的目标:当大量角色的运动变化本身就是收益时,开发者可能愿意接受不同的控制取舍。讨论串

这些个别反馈展示了不同使用目标下的取舍。

当前判断:修复成本和验证成本,已经超过这次接入的收益

在这个项目里,我需要可预测的玩家控制、可信的接触,以及能针对局部问题完成的修复。实验中,控制器从条件构造一路补到相位、支撑锚点、动作库、状态机、连招缓冲和时间重采样。每增加一层,都要重新核对输入、生成结果和最终画面。

第一轮实验结束时,我撤回了演示接入并保留 TensorRT xmake package。之后恢复代码,是为了继续验证四帧放置和动作控制的想法。截至本次更新,最新实验代码仍在本地、尚未提交;这篇文章也尚未发布。

我的当前判断是:这次接入仍未满足项目的玩家控制目标,继续修补的收益不够明确。 这个判断来自当前模型、当前角色和当前控制器的实际体验,无法推导所有使用场景的效果。

下次评估生成式角色控制,我会先在官方骨架上固定一套操作序列:起步、转向、停步、变速和单次攻击。每次修改同时保存输入条件、源骨架和最终角色录像,再比较同一操作下的结果。

这次直到开始做这些对照,左右步幅和待机站姿才逐渐变成能定位的问题。攻击实验还缺少这样的闭环:按键能接出三拳以后,还要能指出哪一段动作违背了操作预期、修改什么条件,以及怎样复现修改前后的差别。


素材与版本说明

  • 本文为本地中文初稿,更新日期:2026-10-31;尚未发布。
  • 手动录像 A:1793311727252,12.184 秒,334 个录制采样画面;手动录像 B:1793314109885,5.939 秒,154 个录制采样画面。它们分别记录了早期行走接入和增加诊断显示后的版本。
  • 早期手动录像保留完整时长和原始速度;正文截图按标注时间提取。全部场景截图与视频已裁去编辑器界面,原始素材另存于 sources/original-images/ 和 sources/original-videos/。录像播放时间与诊断采样时间存在帧级离散,图表使用 CSV 中的时间。
  • 图 5、6、9 是当时反馈的原始截图。图 8、10 来自自动回归。流程图为本次复盘原创绘制。
  • 上游资源与模型卡引用固定到 54fc563aeaaf819a753d72cc9fdc6713989cdd43;接入经历一次撤回和后续恢复,最新实验保持本地未提交状态。
  • 图表计算脚本、取样数据和素材来源见同目录 sources/ 与 build_figures.py。
  • 第七至九阶段依据 temp/motionbricks/placement-comparison/、gait-probes/、phase-fix/、smooth-style/、idle-diagnosis/ 的记录,直行对照与后续交互回归分开叙述。
  • 图 13 与连招录像来自 temp/motionbricks/action-library/combo/,使用模拟按键。最后一次“仍然不好用”的判断来自随后手动操作的反馈;此处没有该次手动操作录像。
  • 裁剪坐标和截帧索引见 sources/crops.json;仅裁剪、排版和视频重新编码,场景几何与角色姿态保持原样。