game-dev-combat-animation

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Game dev: combat animation

游戏开发:战斗动画

Distilled from the Thornvigil knight-and-archer pass (2026-09-30 to 10-01, releases 1.0.71 and 1.0.72). Its outcome:
  • Arms and hands won 5 of 8 blind A/B comparisons against the previous release.
  • The archer's broken anchor and the knight's frozen, straight-armed follow-through were fixed.
  • Seven rounds of fixes came from traps that numbers would have caught earlier. Those traps are listed below.
Read
references/thornvigil.md
for the project's files, commands and current state, and
references/traps.md
before changing keys.
总结自 Thornvigil 的骑士与弓手优化工作(2026-09-30 至 10-01,版本 1.0.71 和 1.0.72)。其成果:
  • 手臂和手部在 8 组盲测 A/B 对比中胜出 5 组。
  • 修复了弓箭手断裂的锚点,以及骑士僵住、手臂笔直的随动收势。
  • 七轮修复都源于一些本可通过数值检查更早发现的陷阱。以下列出了这些陷阱。
请阅读
references/thornvigil.md
,了解项目文件、命令和当前状态;修改关键帧前,请先阅读
references/traps.md
。

The loop

工作循环

  1. Write the standard before touching keys. Extend
    docs/combat-animation-standard.md
    (or the project's equivalent) with the move's own numbered rules:
    • Phases on the game's clock: anticipation, the contact or release on the rule's frame, recovery.
    • Body mechanics, weapon path, camera reads.
    • Mark each rule test (measured) or reviewed (scored from frames).
    • Ground every rule in a real reference: a Tripo Studio motion-capture preset for body mechanics, or coached technique such as the archery shot cycle. Use Tripo presets only; the user has no Mixamo account and declined Quaternius.
  2. Baseline first. Capture both surfaces (the Characters page and in play), keep the frames, and get blind scores before changing anything.
  3. Design keys from anatomy, not from hand positions. For each key pick the upper-arm direction
    u
    , the forearm direction
    f
    and the blade
    b
    , then run
    keydesign.mjs
    . It returns the hand target and flags:
    • raise over 100°;
    • flex outside 12–140°;
    • a blade outside 25–115° off the forearm. Hand keys ride the shoulder; blade and elbow keys are world directions. See
      references/techniques.md
      .
  4. Measure before looking. Bake, then:
    • armcheck.mjs
      for joint ranges and the skin's stretch and crush per arm region on the real mesh;
    • at.mjs
      for the fist and blade at given times;
    • the move's own probe:
      knight-measure.mjs
      ,
      anchor.mjs
      or
      drawfit.mjs
      . Fix numbers that break a rule before spending a capture.
  5. Test. Run the arm-ranges test and the move's tests. When you add a test for a bug, temporarily restore the bug and prove the test fails; a test that reads the same wrong convention as the code passes forever.
  6. Capture both cameras and look yourself at full resolution. A pose that reads well from the front can read broken from the game camera, and the reverse. Diff each capture against the previous round to be sure it is new.
  7. Judge. Use two blind critics with a fixed rubric (5 criteria × 0–2; the lower score counts) and a blind A/B against the last release with identical sheet titles. Then verify every claim against full-resolution frames and live-rig numbers before acting on it. See
    references/review.md
    and
    templates/
    .
  8. Ship by the project's rules: tests, build, changelog with real screenshots, push, sizes, publish. Use the
    workflow-ship-change
    skill. If a pushed but unpublished release regresses, correct it in place with a follow-up commit; don't add a version for something players never saw.
  9. Show it. When asked for videos, capture at 30 fps on the move's own clock, place the Characters page and in-play views side by side, and play real speed then quarter speed (
    vidcompose.py
    +
    encode.swift
    ).
  1. 先制定标准,再修改关键帧。 使用该动作自身的编号规则扩展
    docs/combat-animation-standard.md
    (或项目中的等价文档):
    • 按游戏时钟划分阶段:预备期、在规则指定帧发生接触或释放、恢复期。
    • 身体力学、武器路径、镜头可读性。
    • 将每条规则标记为 test(实测)或 reviewed(依据帧评分)。
    • 每条规则都要有真实依据:身体力学可参考 Tripo Studio 动作捕捉预设,或采用射箭拉放循环等经过指导的技术动作。只使用 Tripo 预设;用户没有 Mixamo 账号,并已拒绝使用 Quaternius。
  2. 先建立基线。 采集两个界面的画面(Characters 页面和游戏内画面),保留帧,并在修改任何内容前获取盲评分。
  3. 依据解剖结构而不是手部位置设计关键帧。 为每个关键帧选取上臂方向
    u
    、前臂方向
    f
    和刀刃方向
    b
    ,然后运行
    keydesign.mjs
    。它会返回手部目标位置,并标记:
    • 抬举角度超过 100°;
    • 屈曲角度不在 12–140° 范围内;
    • 刀刃与前臂的夹角不在 25–115° 范围内。 手部关键帧以肩部为参照;刀刃和肘部关键帧使用世界方向。参见
      references/techniques.md
      。
  4. 先测量,再观察。 烘焙后执行:
    • armcheck.mjs
      :在真实网格上检查关节范围,以及各手臂区域的蒙皮拉伸和挤压情况;
    • at.mjs
      :在指定时间检查拳头和刀刃;
    • 该动作专用的探针:
      knight-measure.mjs
      、
      anchor.mjs
      或
      drawfit.mjs
      。 先修复违反规则的数值,再投入采集时间。
  5. 测试。 运行手臂范围测试和该动作自己的测试。为缺陷添加测试时,暂时恢复缺陷并证明测试会失败;如果测试与代码采用同样错误的约定,就会永远通过。
  6. 采集两个摄像机视角,并以全分辨率亲自查看。 前视角下表现良好的姿势,从游戏摄像机中看可能显得断裂,反之亦然。将每次采集与上一轮进行差异对比,确认内容确实发生了变化。
  7. 评判。 使用两名盲审评审员和固定评分表(5 项标准 × 0–2 分;采用两者中的较低分)进行评判,并使用标题相同的评分表,将当前版本与上一发布版本进行盲测 A/B 对比。随后,在采取行动前,务必依据全分辨率帧和实时绑定数值验证每条评审意见。参见
    references/review.md
    和
    templates/
    。
  8. 交付。 按照项目规则执行:运行测试、构建、生成带真实截图的变更日志、推送、记录体积并发布。使用
    workflow-ship-change
    skill。如果已推送但未发布的版本出现回归,应通过后续提交原地修正;不要为玩家从未见到的内容新增版本号。
  9. 展示。 当被要求提供视频时,按该动作自身的时钟以 30 fps 采集,将 Characters 页面与游戏内画面并排放置,并以原速和四分之一速度播放(
    vidcompose.py
    +
    encode.swift
    )。

The arm and hand rules

手臂与手部规则

The rig has no twist or corrective bones; past these ranges the skin visibly wrings, crushes or stretches. Every frame of every strike stays inside them, on both bodies, measured on the real skinned mesh.
RuleLimit
Elbow flexion10–152°; the striking or drawing arm keeps ≥20° through the middle 80% of the move
Contact reachsword hand ≥60% of arm length from the shoulder at contact (reach into the blow, never lock)
Wristbend ≤50°, roll ≤45°; sword wrist capped at 40°; a drawing hand held straight
Twistforearm roll ≤52°, upper-arm roll ≤52°
Raise≤105° from hanging (shoulder skin crushes beyond); no overhead raises
Skinthe worst 1% of each arm or hand region's edges: stretch ≤2×, crush ≤3× against the bind
Handsalways in a pose: fist on a grip, hook on a string (set → loose → follow-through), relaxed when empty; never splayed or clawed
Pathshands ride their shoulders and arc about them between keys; blade keys stay reachable (25–115° off the forearm)
Full rules, with the reasons and the tests that enforce them, are in
references/rules.md
.
绑定系统没有扭转骨骼或校正骨骼;超出这些范围,蒙皮会出现明显的拧转、挤压或拉伸。每次攻击的每一帧在两种角色身体模型上都必须处于这些范围内,并在真实蒙皮网格上进行测量。
规则限制
肘部屈曲10–152°;击打臂或拉弓臂在动作中间 80% 的过程中始终保持 ≥20°
触达距离接触时,持剑手与肩膀的距离 ≥ 臂长的 60%(手臂要伸入打击中,绝不锁死)
腕部弯曲 ≤50°,旋转 ≤45°;持剑手腕上限为 40°;拉弓手保持伸直
扭转前臂旋转 ≤52°,上臂旋转 ≤52°
抬举相对自然下垂姿势 ≤105°(超过此角度会挤压肩部蒙皮);不得过度抬臂
蒙皮对每个手臂或手部区域边缘最差的 1%:相对绑定姿势,拉伸 ≤2×,挤压 ≤3×
手部始终保持有效姿势:握住武器时握拳,拉弦时勾弦(上弦 → 松弦 → 随动),空手时放松;绝不能五指张开或呈爪状
路径手部关键帧随肩移动,并在关键帧之间绕肩形成弧线;刀刃关键帧必须处于可及角度(与前臂成 25–115° 夹角)
完整规则、相关原因以及执行这些规则的测试见
references/rules.md
。

Techniques that worked

有效技术

  • Shoulder-relative hands with arc interpolation. A fixed hand target that the lunging trunk drives the shoulder into crushes the arm, and a straight-line lerp folds the elbow shut mid-way.
  • Aim the forearm, not the wrist. With the wrist capped, the blade lands on the cone the forearm roll allows. To change the blade, change
    f
    .
  • Read blade keys in world space. With the trunk wound back about 70°, "over the sword shoulder" points across behind the head. Tilt the chamber tip-up so it reads as a diagonal.
  • Keep the follow-through moving.
    • Quick cut: carry the hand down past the shield-side hip on a bent elbow, with the blade still on the line.
    • Heavy cut: sink across, then rebound with the elbow folding.
    • Never hold an arm out at the foe with the blade hanging.
  • Bow draw. Anchor under the jaw beside the chin, where the hand stays in sight from both cameras. The draw elbow rides 6–8 cm under the arrow. Turn the hips side-on, which fixed draw-shoulder crush better than shrug or elbow poles. Hold the hook through the loose, then send the hand out past the shoulder rather than round the head.
  • Kinetic chain. Hips lead the chest, and the chest leads the arm. A bow's recoil answers the loose and never leads it.
  • 以肩部为参照的手部关键帧配合弧线插值。 如果手部目标固定,向前冲刺的躯干会带动肩部并挤压手臂;直线 lerp 则会让肘部在中途闭合。
  • 瞄准前臂,而不是手腕。 手腕活动受限时,刀刃只能落在前臂旋转所允许的锥形区域内。要改变刀刃方向,应改变
    f
    。
  • 在世界空间中解读刀刃关键帧。 躯干后仰约 70° 时,“越过持剑肩”会指向脑后。将蓄势端向上倾斜,使动作呈现为对角线姿态。
  • 让随动持续运动。
    • 快速斩击:肘部保持弯曲,让手沿动作线下移至盾牌一侧髋部下方,同时保持刀刃仍处于原动作线上。
    • 重型斩击:先斜向下沉,再随肘部收拢而回弹。
    • 绝不要把持剑臂伸向敌人并让刀刃悬垂。
  • 弓术拉弓。 将锚点放在下巴旁、下颌下方,确保手在两个摄像机视角中都清晰可见。拉弓肘部保持在箭杆下方 6–8 cm 处。髋部转向侧向,这比耸肩或把肘部支成直杆的姿势更能消除拉弓肩部的挤压。保持勾弦直至松弦,然后将手向肩外送出,而不是绕过头部。
  • 发力链。 髋部引导胸部,胸部引导手臂。弓的后坐力应回应松弦动作,绝不能抢在松弦之前发生。

Traps that each cost a round

每次都导致一轮返工的陷阱

references/traps.md
has symptom → cause → fix for each. The short list:
  • Bone axes. The HumGen
    head
    bone is +Y forward and +Z down. Check any bone-local offset against mesh landmarks (
    face.mjs
    ).
  • Masked failures. The first failing assertion hides every later move in the same test loop, and the first failing gender hides the other.
  • Camera reads.
    • A hand by the neck reads as "behind the head" from the game camera.
    • A blade pointing at the camera reads as "hanging".
    • An elbow bent in the view plane reads as straight.
  • Critic misreads. Thumbnails mislead critics. Check full-resolution frames and the live rig before changing anything.
  • Capture traps.
    • Never edit
      src
      while a capture runs.
    • After
      location.reload()
      , wait before evaluating the next script.
    • Hand-stepped frames are not FPS measurements.
references/traps.md
针对每种问题都给出了症状 → 原因 → 修复方法。简要列表如下:
  • 骨骼轴向。 HumGen 的
    head
    骨骼以 +Y 为前、+Z 为下。将任何骨骼局部偏移与网格上的解剖特征点进行核对(
    face.mjs
    )。
  • 被掩盖的失败。 测试循环中第一个失败的断言会掩盖同一循环内后续所有动作,第一个失败的性别模型也会掩盖另一个性别模型的问题。
  • 镜头可读性。
    • 颈部旁的手从游戏摄像机中看会被理解为“在脑后”。
    • 指向摄像机的刀刃会被理解为“悬垂”。
    • 在视线平面内弯曲的肘部会被看成伸直。
  • 评审误读。 缩略图会误导评审员。修改任何内容前,先核对全分辨率帧和实时绑定。
  • 采集陷阱。
    • 采集运行时绝不修改
      src
      。
    • 执行
      location.reload()
      后,先等待,再求值下一个脚本。
    • 手动逐帧步进得到的画面不能作为 FPS 测量结果。

Report

报告

Lead with what changed in the moves and whether it is live. Then give:
  • a scores table: before → after, lower of the two critics, per surface;
  • the A/B result;
  • the faults still open, named by frame;
  • the tests added;
  • file and push sizes.
Say plainly when a score sits short of the target and why.
先说明各个动作有哪些改动,以及改动是否已经上线。然后给出:
  • 评分表:改动前 → 改动后、每个界面上两名评审员中的较低分;
  • A/B 对比结果;
  • 仍未解决的缺陷,并注明对应帧;
  • 新增的测试;
  • 文件体积和推送体积。
如果评分未达到目标,应直截了当地说明差距及原因。