# 横版 3D 格斗小游戏开发设计文档 **2.5D · 1v1 · 帧数据驱动 · 单机原型基线** | **版本** | v1.0 | |--------------|------------------------------------| | **日期** | 2026-08-10 | | **技术基线** | 引擎无关;示例采用 Unity / C# 命名 | > 目标:用最小但正确的战斗架构,实现行走、跳跃、格挡、拳脚、必杀技、超必杀技、命中反馈与完整回合流程;同时为后续角色扩展、训练模式和回滚联机保留清晰边界。 | **核心战斗** | **数据驱动** | **可验证** | | --- | --- | --- | | 输入缓冲 · 状态机 · 命中结算 | 招式帧表 · 判定轨迹 · 资源规则 | 帧步进 · Hitbox 调试 · 验收用例 | **DOCUMENT CONTROL** # 文档控制与阅读说明 本文档是面向小型团队或个人开发者的可执行设计基线。它同时覆盖玩法规则、核心战斗技术方案、数据结构、调试工具、开发计划与验收标准。所有数值均为首轮灰盒原型建议值,应通过手感测试迭代。 | **字段** | **内容** | |------------------|----------------------------------------------------| | **项目类型** | 横版 3D(2.5D)1v1 对战格斗小游戏 | | **首发平台** | PC;键盘与手柄;本地双人或玩家对 AI | | **画面实现** | 3D 角色与场景,战斗逻辑约束在水平轴与垂直轴 | | **战斗基线** | 固定 60 Tick;帧数据驱动;运动学角色控制器 | | **参考代码风格** | Unity / C# 命名;可映射至 Unreal、Godot 或自研引擎 | | **目标读者** | 程序、策划、动画、特效、测试与制作人 | > **关键边界** > > MVP 不做联网、投技、复杂防御资源、角色养成与剧情。先确保“输入可靠、状态可控、命中可解释、帧数据可调”,再增加内容。 ## 术语约定 | **术语** | **定义** | |--------------------------------|-------------------------------------------------------------------------------| | **战斗 Tick** | 战斗逻辑更新单位;固定为每秒 60 次,与渲染帧率解耦。 | | **起手 / 持续 / 收招** | Startup / Active / Recovery;攻击从输入到判定生效,再到恢复可行动的三个阶段。 | | **HitStop** | 命中瞬间双方短暂停顿,用于强化重量感;不等同于受击硬直。 | | **HitStun / BlockStun** | 命中硬直 / 格挡硬直;期间角色不能自由行动,但可受特定规则影响。 | | **HitBox / HurtBox / PushBox** | 攻击判定 / 可受击判定 / 角色实体推挤判定。 | | **取消窗口** | 允许当前动作提前转入指定动作的帧区间。 | | **指令宽容** | 方向输入允许的总时间、相邻输入最大间隔、斜方向替代等容错规则。 | ## 目录 | **01 项目定位与设计目标** | **11 动画、特效、音效与镜头** | |-----------------------------|-------------------------------| | 02 MVP 范围与内容规格 | 12 技术架构与更新顺序 | | 03 比赛规则与战斗空间 | 13 数据配置与资源规范 | | 04 输入、缓冲与指令识别 | 14 UI、回合流程与设置 | | 05 角色状态机与转移优先级 | 15 AI 与训练木桩 | | **06 行走、跳跃与角色运动** | **16 性能、回放与联机预留** | | 07 拳脚攻击与招式时间轴 | 17 调试工具与可观测性 | | 08 格挡、防御与受击规则 | 18 开发里程碑与任务拆分 | | 09 HitBox 与命中结算管线 | 19 测试方案与验收标准 | | 10 必杀技、超必杀技与能量 | 20 风险、原创边界与附录 | **PRODUCT VISION** # 01 项目定位与设计目标 本项目是一款使用 3D 角色和场景、但将对战规则限制在二维战斗平面的 1v1 格斗小游戏。玩家通过走位、跳跃、格挡、拳脚、必杀技与超必杀技争夺回合胜利。重点不是堆叠招式数量,而是建立清晰、稳定、可调试的战斗内核。 ## 1.1 玩家体验目标 - 输入响应明确:按键、方向与指令不会因为渲染帧率或动画事件而随机失效。 - 攻防结果可理解:为什么命中、为什么被格挡、为什么发生交易命中,都能通过调试数据解释。 - 打击有重量:命中停顿、受击动作、音效、火花、震屏与击退在同一事件上同步。 - 学习成本可控:MVP 只提供少量高辨识度招式,先形成“近身、对空、飞行道具、爆发技”的完整循环。 - 内容可扩展:新增角色主要通过配置数据、动画和判定轨迹完成,避免复制并修改大量角色逻辑。 ## 1.2 核心循环 | **阶段** | **玩家行为** | **系统反馈** | |-----------------|------------------------------|--------------------------------| | **中立博弈** | 前后移动、试探、跳跃、预判 | 距离、站位、能量与时间形成压力 | | **进攻确认** | 拳脚命中或迫使对手格挡 | HitStop、硬直、推远、命中特效 | | **连段 / 取消** | 用轻攻击确认,再取消到必杀技 | 连击数、伤害缩放、资源增长 | | **防守反击** | 格挡、后退、等待收招空隙 | 格挡硬直、削血、反击提示 | | **资源爆发** | 积满能量后使用超必杀技 | 屏幕冻结、镜头强化、多段命中 | | **回合结算** | KO 或时间结束 | 慢镜、胜负 UI、重开或下一回合 | ## 1.3 设计原则 > **1.** 战斗逻辑先于表现:战斗结果由数据与状态决定,动画、特效和镜头只消费结果。 > > **2.** 整数帧优先:所有招式时序、无敌、取消与硬直均用战斗 Tick 表达。 > > **3.** 单一结算入口:所有近战、飞行道具和超必杀命中都进入同一 HitResolver。 > > **4.** 配置优先于分支:角色差异放入 CharacterData、MoveData 与 HitboxTrack,而不是散落在代码中的 if/else。 > > **5.** 调试能力属于产品功能:从第一周就提供帧步进、输入历史和判定框显示。 > **成功标准** > > 两个相同灰盒角色也能玩出完整回合:走位可控、跳跃轨迹稳定、拳脚可命中/格挡、必杀与超杀可识别、KO 能结算;全流程无随机漏判和状态卡死。 **SCOPE** # 02 MVP 范围与内容规格 ## 2.1 首个可玩版本 | **优先级** | **功能** | **MVP 规格** | |--------------|----------|----------------------------------------------------------| | **P0 必须** | 角色移动 | 前走、后走、转身、蹲下、前跳、后跳、垂直跳、落地硬直 | | **P0 必须** | 基础攻击 | 站立轻拳/重拳/轻脚/重脚,蹲轻脚,跳攻击;至少 6 个普通技 | | **P0 必须** | 防御 | 按住背向方向格挡;站防、蹲防;格挡硬直、推远与削血规则 | | **P0 必须** | 命中 | HitBox/HurtBox、HitStop、HitStun、击退、浮空、击倒、KO | | **P0 必须** | 特殊招式 | 每角色 3 个必杀技:飞行道具、对空技、突进技 | | **P0 必须** | 爆发资源 | 0–100 超必杀能量;每角色 1 个超必杀技 | | **P0 必须** | 比赛流程 | 倒计时、生命、能量、局数、KO、时间结束、重开 | | **P1 建议** | 对战对象 | 本地双人 + 简单 AI;训练木桩 | | **P1 建议** | 调试 | 输入历史、帧计数、判定框、命中日志、帧步进 | | **暂不实现** | 复杂系统 | 投技、拆投、空防、弹反、防御槽、角色养成、联网匹配 | ## 2.2 内容量建议 | **内容项** | **原型下限** | **首个完整 Demo** | |--------------|------------------|---------------------------| | **角色** | 1 个角色镜像对战 | 2 个原创角色 | | **场景** | 1 个灰盒场景 | 1 个完整场景 + 1 个训练场 | | **普通技** | 每角色 6 个 | 每角色 10–12 个 | | **必杀技** | 每角色 2 个 | 每角色 3 个 | | **超必杀技** | 每角色 1 个 | 每角色 1 个 | | **AI 难度** | 1 档 | 3 档 | | **回合规则** | 一局定胜负 | 三局两胜、99 秒 | > **范围控制建议** > > 先用胶囊体、基础动作和纯色特效完成“第一可玩”;在手感通过前,不投入角色建模、复杂镜头和大量动作。任何新增功能都必须说明它改善了哪一种攻防决策。 ## 2.3 非功能目标 - 标准 PC 在 1080p 下稳定 60 FPS;战斗 Tick 永远保持 60 Hz。 - 单次对战可从输入流重放,重放结果在同版本、同平台上保持一致。 - 角色招式数据修改后无需改核心代码即可生效。 - 战斗关键路径不产生持续 GC;飞行道具、命中特效和飘字使用对象池。 - 控制支持手柄与键盘重绑定,并提供震屏、闪光强度与输入显示开关。 **RULES & SPACE** # 03 比赛规则与战斗空间 ## 3.1 默认比赛规则 | **参数** | **默认值** | **说明** | |----------------|------------------|------------------------------------| | **局制** | 三局两胜 | 原型阶段可切换为一局定胜负 | | **回合时间** | 99 秒 | 使用战斗时间;暂停与回合演出不计时 | | **最大生命** | 1000 | 便于用整数表达伤害与缩放 | | **超必杀能量** | 0–100 | 命中、格挡与受击均可按招式配置增长 | | **时间结束** | 生命百分比高者胜 | 相同则判平局并重开该回合 | | **KO 判定** | 生命值 ≤ 0 | 本 Tick 结算完成后进入 KO 状态 | ## 3.2 坐标系与战斗平面 建议将 X 轴定义为左右移动,Y 轴定义为高度,Z 轴为场景深度。角色逻辑位置始终投影到固定的战斗平面 Z = 0;3D 模型可在表现层有轻微深度偏移,但 PushBox、HurtBox 与 HitBox 均在同一逻辑平面计算。 - 舞台边界:X ∈ \[−StageHalfWidth, +StageHalfWidth\],角色中心不可越界。 - PushBox:两个角色不可穿透;先求期望位移,再按质量和边界分摊重叠量。 - 面对方向:每个 Tick 末根据双方 X 位置决定;攻击不可转身的帧区间保持原朝向。 - 交叉攻击:双方交换位置后,下一 Tick 更新面对方向;当前 Tick 的方向输入按 Tick 开始时朝向解释。 - 镜头:始终看向两人中点,并用距离和舞台边界控制缩放与平移。 ## 3.3 战斗时间模型 > **固定战斗 Tick** > > 渲染可以是 60、120 或更高 FPS,但输入采样、状态推进、移动、碰撞与命中结算都以固定 1/60 秒为单位。动画播放速度由当前招式帧映射,不反过来驱动战斗结果。 | **时间域** | **是否受 HitStop 影响** | **典型内容** | |----------------------|-------------------------|---------------------------------------| | **BattleTime** | 是 | 招式帧、移动、飞行道具、受击/格挡硬直 | | **PresentationTime** | 可选 | 粒子、镜头震动、音效尾音、UI 动画 | | **RealTime** | 否 | 暂停菜单、设备重连、加载与调试界面 | **INPUT** # 04 输入、缓冲与指令识别 ## 4.1 默认操作映射 | **动作** | **键盘示例** | **手柄示例** | **规则** | |-------------|---------------|-----------------|------------------------------------| | **方向** | WASD / 方向键 | 十字键 / 左摇杆 | 8 方向归一化;按角色朝向转换为前后 | | **轻拳 LP** | J | X / □ | 快速、短距离、低伤害 | | **重拳 HP** | K | Y / △ | 较慢、高伤害、可对空 | | **轻脚 LK** | U | A / × | 中短距离、可做低段 | | **重脚 HK** | I | B / ○ | 长距离、较大收招 | | **暂停** | Esc | Menu / Options | 仅比赛允许时打开 | *格挡默认不占独立按键:按住“远离对手”的方向进入格挡意图。可在辅助模式中增加 Guard 键。* ## 4.2 输入帧结构 每个渲染帧读取设备输入,将结果写入 InputBuffer;每个战斗 Tick 消费一个归一化输入快照。缓冲区建议保存最近 30–45 Tick,用于指令识别、输入显示、回放与问题复现。 | **字段** | **类型** | **用途** | |--------------------|--------------|------------------------------------------| | **Tick** | int | 输入发生的战斗 Tick | | **Direction** | enum 1–9 | 数字小键盘方向;5 为中立 | | **PressedMask** | bitmask | 本 Tick 新按下的攻击键 | | **HeldMask** | bitmask | 本 Tick 持续按住的攻击键 | | **ReleasedMask** | bitmask | 本 Tick 释放的攻击键;可用于负边输入扩展 | | **FacingSnapshot** | Left / Right | 用于将世界方向转换为相对方向 | | **ConsumedFlags** | bitmask | 避免同一次按键被多个动作重复消费 | ## 4.3 指令识别规则 - 方向按“相对朝向”解释:6 始终代表前,4 始终代表后。 - 从攻击键按下 Tick 向前回溯方向序列,而不是从最早输入向后搜索。 - 每条指令配置总窗口、相邻步骤最大间隔、是否允许斜方向替代、是否允许跳过中立。 - 同 Tick 多条指令成立时,按“超必杀 \> 必杀技 \> 特殊普通技 \> 普通技”排序。 - 动作进入后消费相关按键与方向片段,避免一个输入同时触发两个动作。 - 推荐首版宽容:必杀总窗口 12–16 Tick,超必杀 20–24 Tick,按键缓冲 4–6 Tick。 | **招式类型** | **输入示例** | **匹配序列** | **宽容建议** | |--------------|-----------------|--------------|-------------------------------------| | **飞行道具** | ↓ ↘ → + P | 2, 3, 6 + P | 允许 2,6 或 2,3,6;总窗口 14 Tick | | **对空技** | → ↓ ↘ + P | 6, 2, 3 + P | 允许首个 6 来自前走;总窗口 12 Tick | | **突进技** | ↓ ↙ ← + K | 2, 1, 4 + K | 斜方向必须出现;总窗口 14 Tick | | **超必杀** | ↓ ↘ → ↓ ↘ → + P | 236236 + P | 总窗口 24 Tick;能量必须为 100 | **指令识别伪代码(方向相对角色朝向)** ```csharp bool TryMatch(Command cmd, InputBuffer buffer, int nowTick, Facing facing) { int cursor = nowTick; for (int i = cmd.steps.Count - 1; i >= 0; --i) { cursor = buffer.FindPreviousMatch( cmd.steps[i], cursor, cmd.maxGapTicks, facing); if (cursor < 0) return false; } return nowTick - cursor <= cmd.totalWindowTicks && buffer.HasButtonPress(cmd.buttonMask, nowTick, cmd.buttonBufferTicks); } ``` > **输入可靠性验收** > > 在固定录制的 1000 组输入序列中,识别结果必须完全一致;切换渲染帧率、开启慢动作或发生 HitStop 时,不得改变指令成立结果。 **STATE MACHINE** # 05 角色状态机与转移优先级 角色使用分层状态机:顶层区分 Ground、Air、Attack、Reaction、Down 与 KO,子状态负责行走、跳跃、攻击阶段和受击类型。状态机只处理“角色当前允许做什么”,招式帧表负责“某个动作在第几帧发生什么”。 ```mermaid flowchart LR subgraph A["自然动作链"] G["Ground
Idle / Walk / Crouch / Turn"] -->|跳跃输入| JS["JumpStart"] JS -->|起跳完成| AIR["Air
Jump / Fall"] AIR -->|接地| LAND["Landing"] LAND -->|落地硬直结束| G end subgraph B["主动与防御分支"] READY["Ground / Air
当前可行动"] -->|攻击输入| ATK["Attack
普通技 / 空中攻击"] READY -->|指令成立| SP["Special / Super
指令技 / 资源技"] READY -->|有效格挡姿态| BLK["Block / BlockStun
格挡意图 / 格挡硬直"] ATK -->|动作结束| BACK["返回 Ground / Air"] SP -->|动作结束| BACK BLK -->|硬直结束| BACK end subgraph C["强制中断链(优先级高于普通输入)"] NONKO["任意非 KO 状态"] -->|合法命中| HIT["HitStun / Launch
站立受击 / 浮空"] HIT -->|击倒| DOWN["Knockdown / Wakeup
倒地 / 起身"] DOWN -->|站立恢复或起身完成| GROUND["Ground"] NONKO -->|生命归零| KO["KO / RoundEnd"] HIT -->|受击阶段生命归零| KO end ``` 图 1 角色核心状态与主要转移 ## 5.1 状态清单 | **状态组** | **子状态** | **关键职责** | |--------------|-----------------------------------------------|----------------------------------------------------| | **Ground** | Idle / Walk / Crouch / Turn | 读取移动与攻击输入;处理面对方向与地面摩擦 | | **Air** | JumpStart / Jump / Fall / AirAttack / Landing | 处理起跳锁定、空中速度、接地与落地硬直 | | **Attack** | Startup / Active / Recovery | 推进 MoveTimeline;开放 HitBox、取消窗口与位移曲线 | | **Special** | Special / Super / Cinematic | 资源校验、无敌、飞行道具、屏幕冻结和多段命中 | | **Defense** | Block / BlockStun | 格挡姿态、高低段校验、格挡硬直与推远 | | **Reaction** | HitStun / Launch / WallBounce | 受击、浮空、击退、连段计数与恢复 | | **Down** | Knockdown / Wakeup | 倒地时间、起身无敌与恢复站立 | | **Terminal** | KO / RoundEnd | 禁用输入,播放结算动作与回合流程 | ## 5.2 转移优先级 同一 Tick 可能同时出现 KO、受击、落地、取消与新输入。为避免结果依赖代码调用顺序,所有转移先生成 TransitionRequest,再由统一优先级选择。建议顺序如下: > **1.** KO / RoundEnd:生命归零或回合结束,覆盖所有普通转移。 > > **2.** 强制受击:命中、击倒、浮空;无敌或装甲可在 HitResolver 阶段拦截。 > > **3.** 脚本强制状态:超必杀演出、抓取演出(未来)、出生与回合开场。 > > **4.** 取消转移:命中取消、格挡取消、特殊取消、超必杀取消。 > > **5.** 接地 / 离地:落地、起跳帧结束、被击飞离地。 > > **6.** 自然结束:收招、硬直、起身、转身结束。 > > **7.** 玩家输入:走、蹲、跳、普通攻击、必杀技。 ## 5.3 状态接口 **状态机接口建议** ```csharp interface IFighterState { void Enter(FighterContext ctx, StateEnterArgs args); void PreTick(FighterContext ctx, in InputFrame input); void Tick(FighterContext ctx); // 推进逻辑帧,不直接播放特效 void PostTick(FighterContext ctx); // 生成转移请求与表现事件 void Exit(FighterContext ctx); } struct TransitionRequest { FighterStateId target; int priority; TransitionReason reason; object payload; } ``` > **避免的实现** > > 不要让 Animator StateMachineBehaviour 直接修改生命、开启判定或决定状态转移。动画事件可能因过渡、掉帧、速度变化或跳帧而漏发;它们最多用于非关键音效与装饰。 **MOVEMENT** # 06 行走、跳跃与角色运动 ## 6.1 运动学角色控制器 角色移动使用自定义 Kinematic FighterMotor,而不是依赖动态刚体。每个 Tick 计算期望速度与位移,执行舞台边界、地面检测和 PushBox 修正,再写回逻辑位置。这样能获得稳定、可重放且便于联网预留的结果。 | **参数** | **原型建议值** | **说明** | |------------------|----------------|----------------------------------------| | **前走速度** | 4.2 m/s | 接近对手时略快,鼓励主动走位 | | **后走速度** | 3.4 m/s | 后退不应成为无成本脱离手段 | | **蹲姿移动** | 0 m/s | MVP 中蹲下固定;后续可增加缓慢移动 | | **跳跃初速度** | 8.5 m/s | 通过重力与初速度共同调整弧线 | | **重力** | −28 m/s² | 建议自定义重力,不使用项目全局物理重力 | | **空中水平速度** | 3.2 m/s | 起跳时锁定方向,允许少量空中修正可配置 | | **落地硬直** | 4 Tick | 普通跳落地;空中攻击可配置更长硬直 | | **PushBox 宽度** | 0.75 m | 站立基线;蹲姿可略小 | *上述数值只用于灰盒验证;最终手感应以画面比例、角色身高和攻击距离统一调整。* ## 6.2 行走规则 - 方向输入为 6 时使用前走速度,4 时使用后走速度;“前/后”按角色面对方向解释。 - 攻击、格挡硬直、受击、倒地和大多数必杀技期间不读取普通行走输入。 - 进入 Turn 状态时可锁定 1–2 Tick,防止模型瞬间镜像造成脚步穿帮;逻辑朝向仍在规则允许时更新。 - 两个 PushBox 重叠时,先尝试各自退让一半;一方贴舞台边界时由另一方承担剩余位移。 - 不得用 CharacterController 的自动 StepOffset 造成 Z 轴或高度漂移;地面只允许设计好的坡度或平面。 ## 6.3 跳跃规则 - 跳跃分为 JumpStart、Airborne、Landing。JumpStart 建议 3–4 Tick,期间可被命中。 - 起跳方向在 JumpStart 结束时锁定;垂直跳 X 速度为 0,前后跳使用各自速度。 - 空中不允许再次跳跃;是否允许空中格挡、空中必杀应由角色与招式数据显式配置。 - 接地判定使用脚底 Probe 与上一 Tick 高度,避免高速下落穿透地面。 - 被击飞时使用 ReactionVelocity,不复用普通跳跃状态,以便独立控制重力、弹地和受身。 **角色运动 Tick 伪代码** ```csharp void SimulateMotor(Fighter f) { Vec2 desired = f.State.BuildVelocity(); Vec2 delta = desired * BattleClock.FixedDelta; delta = Stage.ClampToBounds(f.Position, delta, f.PushBox); f.Position += delta; PushSolver.ResolvePair(f, f.Opponent); GroundProbe.ResolveLanding(f); } ``` > **手感调试顺序** > > 先固定角色身高与舞台比例,再调走速和跳跃弧线;随后调攻击距离;最后才调镜头。镜头不能掩盖角色运动本身的问题。 **MOVE SYSTEM** # 07 拳脚攻击与招式时间轴 ## 7.1 普通攻击规格 每个普通技由 MoveData 描述,并由 MoveController 按 Tick 推进。MoveData 不仅记录起手/持续/收招,还包含位移、HitBox 轨迹、伤害、命中效果、取消窗口、资源变化和表现事件。 | **招式** | **定位** | **建议特征** | |-----------------|---------------|--------------------------------------------------| | **站轻拳 LP** | 近距离确认 | 4 Tick 起手;短收招;命中可连自身或取消必杀 | | **站重拳 HP** | 高伤害 / 对空 | 8–10 Tick 起手;大 HitStop;可设置上半身对空判定 | | **站轻脚 LK** | 中距离牵制 | 5 Tick 起手;较长脚部 HitBox;低伤害 | | **站重脚 HK** | 远距离重击 | 10–12 Tick 起手;长收招;可造成击退或击倒 | | **蹲轻脚 2LK** | 低段确认 | 低段;伤害低;命中后可接轻拳或必杀 | | **跳重脚 j.HK** | 跳入攻击 | 空中可用;落地有硬直;根据落点决定正反向 | ## 7.2 招式阶段 | **阶段** | **逻辑** | **可发生事件** | |--------------|--------------------------|------------------------------------------| | **Startup** | 输入已接受,尚无攻击判定 | 前摇位移、无敌/装甲、取消来源检查 | | **Active** | 一个或多个 HitBox 有效 | 命中、格挡、交易命中、多段间隔 | | **Recovery** | HitBox 关闭,等待恢复 | 可被反击;部分招式开放命中取消 | | **End** | 招式完成 | 返回 Idle / Air / Landing 或链入后续动作 | ## 7.3 取消规则 - Whiff Cancel:挥空时允许取消;MVP 默认关闭,避免无限安全试探。 - Hit Cancel:命中后允许普通技取消到指定必杀技。 - Block Cancel:被格挡时也可取消;通常比命中取消列表更严格。 - Chain Cancel:轻攻击可在命中后连到另一轻攻击或指定中攻击。 - Super Cancel:特定必杀技在命中/格挡时可取消为超必杀技。 - 取消只在 MoveData 的帧区间内有效,并且来源、目标、命中状态和资源条件全部满足。 ## 7.4 连段与伤害缩放 | **规则** | **MVP 建议** | |------------------|-----------------------------------------------------------| | **连击成立** | 上一击造成的 HitStun 尚未结束,下一击在恢复前命中 | | **伤害缩放** | 第 1 击 100%,第 2 击 90%,之后每击 −10%,最低 50% | | **最低伤害** | 超必杀最后一击可设 20% 最低保障,避免长连段完全失去终结感 | | **HitStun 衰减** | 连击达到 5 段后每段额外减少 1 Tick,避免无限连 | | **重复招式限制** | 同一浮空连段中关键弹墙/浮空属性只触发一次 | | **连击重置** | 受击者回到可行动状态、倒地结束或回合结算时重置 | > **帧优势的基本检查** > > 命中优势 ≈ HitStun − 攻击者剩余收招;格挡优势 ≈ BlockStun − 剩余收招。MVP 不要求复杂数值,但每个招式都应能从帧表推导“命中后谁先动、格挡后是否可反击”。 **DEFENSE** # 08 格挡、防御与受击规则 ## 8.1 格挡意图 格挡不是一个可以随时强制进入的普通动作,而是角色在可防御状态下、检测到“远离对手”的方向输入后产生的 GuardIntent。HitResolver 在命中 Tick 使用该意图、姿态和攻击段位决定是否格挡成功。 | **攻击段位** | **站立格挡** | **蹲下格挡** | **空中格挡** | |------------------------|--------------|--------------|--------------| | **High 高段** | 可 | 不可 | MVP 不支持 | | **Mid 中段** | 可 | 可 | MVP 不支持 | | **Low 低段** | 不可 | 可 | MVP 不支持 | | **Unblockable 不可防** | 不可 | 不可 | 不可 | ## 8.2 格挡成立条件 - 受击者当前状态允许格挡:Idle、Walk、Crouch 或可取消到格挡的恢复状态。 - 在命中 Tick 开始时存在有效 GuardIntent;方向按该 Tick 的 FacingSnapshot 解释。 - 攻击段位与受击者姿态匹配;不可防或投技类攻击直接绕过。 - 受击者未处于 GuardBreak、KO、不可防演出或明确禁止格挡的动作中。 - 命中来自身后时,MVP 仍按双方逻辑朝向判定;下一 Tick 才更新转身,避免同 Tick 双重解释。 ## 8.3 格挡结果 | **项目** | **建议规则** | |--------------|---------------------------------------------------------------------| | **格挡硬直** | 由攻击 MoveData 给出;轻攻击 6–9 Tick,重攻击 12–18 Tick | | **格挡推远** | 攻击者与防守者按比例分摊;角落时攻击者承担更多反作用位移 | | **削血** | 普通技 0;必杀技 5%–15% 基础伤害;削血不能直接 KO(可配置) | | **能量增长** | 攻击者命中格挡获得少量能量,防守者也获得更少能量 | | **取消规则** | 攻击者可按 MoveData 在格挡后取消;防守者不可在 BlockStun 中普通行动 | | **连续格挡** | BlockStun 期间若新攻击到达,重新计算段位并刷新硬直 | ## 8.4 受击类型 | **类型** | **用途** | **反应** | |----------------|----------------------|----------------------------------| | **LightHit** | 轻拳、轻脚 | 短 HitStop、轻微后仰、短硬直 | | **HeavyHit** | 重拳、重脚、必杀 | 较长 HitStop、明显击退与受击动作 | | **Launch** | 对空或浮空技 | 写入空中速度,进入 Launch 状态 | | **Knockdown** | 扫腿、重击、超杀终结 | 落地后进入倒地与起身流程 | | **Crumple** | 可选的重度受击 | 长站立硬直,可用于超杀前置 | | **CounterHit** | 在对手攻击起手被命中 | 额外伤害或 HitStun,并显示提示 | > **简化建议** > > MVP 先不做完美格挡、弹反、防御槽和受身。防御系统越复杂,越需要额外动画、UI、AI与平衡成本;先把高/中/低段与格挡硬直做正确。 **HIT DETECTION** # 09 HitBox 与命中结算管线 ## 9.1 判定体分类 | **判定体** | **归属** | **用途** | **实现建议** | |------------------|----------------|--------------------------|--------------------------------------| | **PushBox** | 角色 | 角色间实体推挤与角落挤压 | 固定矩形/胶囊;每 Tick 处理一次 | | **HurtBox** | 角色骨骼或姿态 | 可被攻击命中的区域 | 头、躯干、腿等多个盒;随姿态轨迹变化 | | **HitBox** | 招式或飞行道具 | 主动攻击判定 | 仅 Active 帧开启;携带 HitDefinition | | **ProximityBox** | 可选 | 靠近时触发近身普通技 | 只用于选招,不直接造成命中 | | **StageBox** | 场景 | 地面、边界与特殊区域 | 逻辑用简化体,视觉网格不参与战斗碰撞 | ## 9.2 判定轨迹 HitBox 与 HurtBox 不依赖运行时骨骼物理碰撞,而是由可编辑的 BoxTrack 描述。每个 Tick 根据招式帧或姿态帧读取局部位置、尺寸、旋转与标签,再转换到角色逻辑坐标。这样可以稳定调节判定,并在动画替换后保持规则可控。 - 优先使用矩形或胶囊;避免 MeshCollider 和复杂 Convex 碰撞。 - 每个 HitBox 携带 MoveInstanceId + HitGroupId,用于控制同一招式对同一目标的命中次数。 - 多段招式通过不同 HitGroup 或 RehitInterval 配置,不通过重复开关碰撞器猜测。 - 飞行道具使用独立 OwnerId、TeamId 与 ProjectileInstanceId,仍进入统一 HitResolver。 - 调试模式显示红色 HitBox、绿色 HurtBox、蓝色 PushBox,并标注 Tick 与招式 ID。 ```mermaid flowchart TD S1["1. 收集同 Tick 的 HitBox × HurtBox 候选"] --> S2["2. 过滤:阵营、自身、重复命中、无敌 / 装甲"] --> S3["3. 判定格挡、高低段、交叉攻击与反击命中"] --> S4["4. 处理同帧冲突:交易命中 / 显式优先级"] --> S5["5. 计算伤害、连段缩放、削血与资源变化"] --> S6["6. 写入 HitStop、HitStun / BlockStun、击退与浮空"] --> S7["7. 派发视觉事件:特效、音效、震屏、慢镜头"] --> S8["8. 记录 CombatLog 与回放输入,进入下一个 Tick"] ``` 图 2 单个战斗 Tick 内的命中结算顺序 ## 9.3 同帧冲突规则 | **场景** | **规则** | |------------------------------|-----------------------------------------------------------------------| | **双方普通攻击同 Tick 命中** | 默认交易命中:两边都应用结果;除非招式显式配置优先级或无敌 | | **攻击命中飞行道具** | MVP 默认不相互抵消;后续可给飞行道具增加耐久与碰撞层 | | **同一攻击命中多个 HurtBox** | 只生成一个 HitCandidate,使用命中点优先级最高的 HurtBox | | **多段攻击同 Tick 重叠** | 按 HitGroupId 和 RehitInterval 去重;同目标每组最多结算一次 | | **命中与 KO 同 Tick** | 先完成该 Tick 全部合法命中,再按结果进入 KO;表现上可选择超杀终结慢镜 | | **格挡与被绕后同 Tick** | 按 Tick 开始时 FacingSnapshot 判断;下一 Tick 才转身 | ## 9.4 HitResult 数据 **统一命中结果对象** ```csharp struct HitResult { EntityId attacker; EntityId defender; MoveInstanceId moveInstance; HitOutcome outcome; // Hit / Block / Armor / Invulnerable int damage; int chipDamage; int hitStopAttacker; int hitStopDefender; int stunTicks; Vec2 pushback; Vec2 launchVelocity; bool counterHit; bool knockdown; Vec2 contactPoint; } ``` > **实现原则** > > 碰撞系统只回答“哪些判定体发生重叠”;HitResolver 才回答“这次重叠是否有效、是否格挡、造成多少伤害、进入什么状态”。不要把游戏规则写进 OnTriggerEnter。 **SPECIALS & SUPER** # 10 必杀技、超必杀技与能量 ## 10.1 必杀技组合建议 | **招式类型** | **战术作用** | **关键实现点** | |--------------|----------------------------|---------------------------------------| | **能量弹** | 远距离牵制、迫使跳跃或格挡 | 对象池、速度、寿命、命中组、场外回收 | | **对空升击** | 惩罚跳跃、近身反击 | 起手无敌窗口、向上 HitBox、落地收招 | | **突进踢** | 中距离接近、连段收尾 | 位移曲线、墙边推挤、命中/格挡不同收招 | ## 10.2 能量系统 | **事件** | **攻击者获得** | **防守者获得** | |------------------|----------------|----------------| | **普通技命中** | 2–5 | 1–3 | | **普通技被格挡** | 1–3 | 1–2 | | **必杀技命中** | 5–10 | 3–5 | | **必杀技被格挡** | 3–6 | 2–4 | | **受到重击** | — | 5–8 | | **使用超必杀** | 消耗 100 | — | *能量增长应全部来自 MoveData,不写死在攻击类型分支中。* ## 10.3 超必杀执行流程 > **1.** CommandRecognizer 检测到超必杀指令,并确认当前状态允许、能量为 100。 > > **2.** 立即预占资源并创建 SuperMoveInstance,防止同 Tick 重复触发。 > > **3.** 进入 8–15 Tick 的 SuperFreeze:对手、普通飞行道具与比赛计时暂停;施放者按配置推进或保持。 > > **4.** 播放镜头拉近、角色闪光和蓄力音效;逻辑仍由 MoveTimeline 决定无敌与判定开启。 > > **5.** 按多段 HitGroup 依次命中;每段有独立 HitStop、伤害与击退。 > > **6.** 终结段应用 Knockdown 或特殊 KO 镜头;超杀结束后恢复正常镜头与 BattleTime。 | **规则项** | **建议** | |--------------|-------------------------------------------------------| | **超杀输入** | 236236 + 任意拳;总窗口 24 Tick,按键缓冲 5 Tick | | **资源检查** | 必须在动作开始前满足;资源在 Enter 时扣除 | | **起手无敌** | 示例 1–8 Tick;只作为招式数据,不由“超杀”类型自动赋予 | | **画面冻结** | 逻辑冻结与表现冻结分离;UI、音效尾音可继续 | | **连段缩放** | 遵循通用缩放,但终结段可有最低伤害保障 | | **失败处理** | 资源不足时回退到普通拳;不可因指令部分匹配吞掉输入 | > **原创性要求** > > 可以借鉴“飞行道具、对空、突进、超杀冻结”等类型设计,但角色造型、动作轮廓、招式名称、特效、音效、UI 与数值组合应原创,避免直接复刻现有作品。 **PRESENTATION** # 11 动画、特效、音效与镜头 ## 11.1 动画驱动策略 | **内容** | **权威来源** | **说明** | |------------------|-----------------------------|--------------------------------| | **当前动作与帧** | FighterState + MoveTimeline | 动画根据逻辑动作与 Tick 采样 | | **HitBox 开关** | MoveData / HitboxTrack | 不依赖 Animation Event | | **角色位移** | FighterMotor / MotionCurve | 普通战斗禁用自由 Root Motion | | **受击与格挡** | HitResult | 结果确定后触发对应表现 | | **音效与特效** | PresentationEvent | 允许丢帧补播,但不影响战斗结果 | | **镜头** | CameraDirector | 消费角色位置与命中事件 | ## 11.2 动画状态建议 - 基础层:Idle、WalkF、WalkB、Crouch、Turn、JumpStart、JumpUp、Fall、Landing。 - 攻击层:每个普通技、必杀技与超必杀独立 Clip;按 MoveId 显式切换。 - 受击层:轻/重受击、上段/下段格挡、浮空、倒地、起身、KO。 - 面部或上半身叠加层仅用于非关键表现,不改变 HurtBox 和战斗姿态。 - 动画过渡时间应很短且可预测;攻击动作通常使用 0 或 1 Tick 的逻辑切换。 ## 11.3 打击反馈事件包 | **反馈** | **轻击** | **重击 / 必杀** | **超必杀终结** | |-------------|--------------|------------------------|--------------------------| | **HitStop** | 4–6 Tick | 7–11 Tick | 10–16 Tick | | **火花** | 小型、短寿命 | 较大、方向性强 | 多层特效 + 屏幕闪光 | | **音效** | 清脆 | 低频冲击 + 武器/元素层 | 专属终结音与低频冲击 | | **震屏** | 0–2 px | 3–7 px | 8–14 px;可在设置中减弱 | | **镜头** | 通常不变 | 轻微推近或冲击抖动 | 拉近、冻结、跟随终结动作 | | **飘字** | 可选 | Counter / Punish 提示 | Super / KO 强调 | ## 11.4 镜头规则 - 基础镜头朝向战斗平面,目标点为两角色中点;距离随角色间距变化。 - 确保两人屏幕边缘留有安全边距,且舞台边界不会暴露未制作区域。 - 跳跃时相机只跟随一定比例的 Y 高度,避免频繁上下晃动。 - HitStop 期间可添加短促 Impulse,但相机位置插值需使用 PresentationTime。 - 超杀镜头必须有超时回退;角色被 KO、演出被中断或对象销毁时强制恢复基础镜头。 > **无障碍与舒适度** > > 设置中提供“震屏强度、闪光强度、手柄震动、动态镜头”开关。关闭这些效果不应改变 HitStop、输入、判定和比赛结果。 **ARCHITECTURE** # 12 技术架构与更新顺序 ```mermaid flowchart TB subgraph DATA["输入与数据"] CD["Character / Move / Stage Data"] IB["InputBuffer"] --> CR["CommandRecognizer"] end subgraph COMBAT["战斗域"] BC["BattleClock
固定 60 Tick"] FC["FighterController
StateMachine + Motor"] MF["MatchFlow"] MC["MoveController
招式时间轴"] CW["CollisionWorld
Push / Hurt / Hit Box"] HR["HitResolver
统一命中结算"] PS["ProjectileSystem"] end subgraph PRESENT["表现层"] VA["VFX / Audio / 动画"] CAM["CameraDirector"] HUD["HUD / 菜单"] end CD --> FC CD --> MC CD --> PS CR --> FC BC --> FC BC --> MF FC --> MC FC --> CW MC --> CW CW --> HR HR --> FC HR --> PS PS --> CW MF -.-> HUD FC -.-> VA FC -.-> CAM FC -.-> HUD HR -.-> VA HR -.-> CAM ``` 图 3 推荐的战斗域模块划分 ## 12.1 核心模块 | **模块** | **职责** | **禁止事项** | |-----------------------|------------------------------------------|--------------------------------| | **BattleClock** | 固定 Tick、暂停、HitStop 域与帧步进 | 不读取玩家输入,不直接控制动画 | | **InputService** | 设备采样、重绑定、写入 InputBuffer | 不决定招式,不改变角色状态 | | **CommandRecognizer** | 匹配指令并生成动作请求 | 不扣资源,不直接播放动画 | | **FighterController** | 聚合状态机、运动、生命、能量与动作实例 | 不直接搜索场景对象 | | **MoveController** | 按 Tick 推进招式事件与取消窗口 | 不直接结算伤害 | | **CollisionWorld** | 构建判定体、收集重叠候选 | 不处理格挡、伤害或 KO | | **HitResolver** | 过滤、格挡、伤害、硬直、击退、资源与日志 | 不依赖特效对象是否存在 | | **ProjectileSystem** | 生成、推进、回收飞行道具 | 不绕过 HitResolver | | **MatchFlow** | 开场、计时、KO、回合与胜负 | 不持有角色招式细节 | | **Presenter** | 动画、VFX、音效、镜头、HUD | 不反向决定战斗逻辑 | ## 12.2 每 Tick 更新顺序 > **1.** InputService 将设备状态汇总为 InputFrame,并写入每个玩家的 InputBuffer。 > > **2.** BattleClock 判断全局暂停、超杀冻结与各实体 HitStop,确定本 Tick 谁可以推进。 > > **3.** Fighter PreTick:识别指令、生成转移请求、处理已到期硬直。 > > **4.** 状态机提交最高优先级转移;MoveController 推进当前招式帧并生成判定轨迹。 > > **5.** FighterMotor 与 ProjectileSystem 计算位移;Stage/PushSolver 修正边界和角色重叠。 > > **6.** CollisionWorld 重建本 Tick 的 Push/Hurt/Hit Box 并收集 HitCandidate。 > > **7.** HitResolver 对全部候选排序和结算,写入生命、能量、硬直、击退与新状态请求。 > > **8.** MatchFlow 检查 KO、时间结束与回合转换。 > > **9.** Presenter 消费本 Tick 的只读快照与 PresentationEvent,更新动画、特效、音效、镜头和 HUD。 > > **10.** CombatLog 记录输入摘要、状态摘要与命中结果,用于回放和问题复现。 **战斗主循环伪代码** ```csharp void BattleTick() { inputService.CaptureTickInputs(); battleClock.BeginTick(); foreach (var fighter in fighters) fighter.PreTick(); foreach (var fighter in fighters) fighter.CommitTransition(); foreach (var fighter in fighters) fighter.SimulateMoveAndMotor(); projectileSystem.Simulate(); collisionWorld.BuildSnapshot(fighters, projectiles); hitResolver.Resolve(collisionWorld.CollectHitCandidates()); foreach (var fighter in fighters) fighter.PostTick(); matchFlow.EvaluateRound(); combatLog.RecordSnapshot(); presenter.PublishFrame(); } ``` ## 12.3 事件分类 | **事件类型** | **是否可丢失** | **例子** | |------------------------|-----------------|----------------------------------------| | **Domain Command** | 不可 | 开始招式、扣能量、应用 HitResult | | **Domain Event** | 不可 | FighterHit、RoundKO、ProjectileSpawned | | **Presentation Event** | 可补播 / 可降级 | HitSpark、CameraShake、PlaySfx | | **Telemetry Event** | 可批量 | 输入统计、帧耗时、招式使用率 | **DATA** # 13 数据配置与资源规范 ## 13.1 CharacterData | **字段组** | **示例字段** | |--------------|----------------------------------------------------------| | **身份** | CharacterId、显示名、阵营、默认皮肤 | | **体型** | 身高、PushBox、站立/蹲姿 HurtBox 轨迹 | | **移动** | 前走/后走速度、跳跃初速度、重力、落地硬直 | | **资源** | 最大生命、最大能量、初始能量、受击能量倍率 | | **动作映射** | Idle、Walk、Jump、Block、Hit、KO 与 MoveId 列表 | | **表现** | AnimatorProfile、VFXProfile、AudioProfile、CameraProfile | ## 13.2 MoveData 核心字段 | **字段组** | **字段** | **说明** | |------------|---------------------------------------|-------------------------------------------------------| | **标识** | MoveId / DisplayName / Tags | 唯一 ID、编辑器名称与 Normal/Special/Super/Air 等标签 | | **输入** | CommandId / Button / AllowedStates | 指令、攻击键、允许起招状态 | | **时序** | Startup / ActiveSegments / Recovery | 全部使用整数 Tick | | **命中** | Damage / HitLevel / HitStop / HitStun | 伤害、高低段、停顿与硬直 | | **位移** | MotionCurve / Pushback / Launch | 攻击者位移、受击推远与浮空速度 | | **判定** | HitboxTrack / HurtboxOverride | 逐 Tick 判定轨迹与姿态覆盖 | | **防御** | BlockStun / Chip / GuardPush | 被格挡后的效果 | | **资源** | MeterGain / MeterCost | 命中、格挡、挥空与使用成本 | | **取消** | CancelWindows / CancelTargets | 时间区间、命中条件和目标标签 | | **特殊** | Invuln / Armor / CounterHitBonus | 无敌、装甲、反击奖励 | | **表现** | AnimationId / VFX / SFX / CameraCue | 只读消费的表现事件 | **Unity 风格的数据对象示例** ```csharp [CreateAssetMenu(menuName = "Fighting/Move Data")] public sealed class MoveData : ScriptableObject { public string moveId; public MoveTag tags; public CommandData command; public int startupTicks; public ActiveSegment[] activeSegments; public int recoveryTicks; public HitDefinition hit; public HitboxTrack hitboxTrack; public MotionTrack motionTrack; public CancelWindow[] cancelWindows; public InvulnerabilityWindow[] invulnerability; public PresentationCue[] presentation; } ``` ## 13.3 资源目录建议 **建议的目录与归属** ```text Assets/Game/ ├── Battle/ │ ├── Core/ # Clock、状态机、命中、运动、回放 │ ├── Data/ # CharacterData、MoveData、StageData │ ├── Editor/ # 帧表、判定轨迹与预览工具 │ └── Debug/ # Hitbox、输入、日志、帧步进 ├── Characters// │ ├── Animations/ │ ├── Moves/ │ ├── HitboxTracks/ │ ├── VFX/ │ ├── Audio/ │ └── Prefabs/ ├── Stages// ├── UI/ └── Tests/ ├── Unit/ ├── Simulation/ └── PlayMode/ ``` ## 13.4 命名与版本 - 稳定 ID 使用小写蛇形:hero_01、st_lp、sp_projectile、su_finisher;显示名可本地化。 - 逻辑数据与表现资源分离:MoveData 不直接引用场景对象,只引用可加载资源 ID。 - 数据增加 schemaVersion;重大字段变更提供迁移脚本,而不是手工逐个修复。 - 所有平衡数值变更进入版本控制,并在提交说明中写明“旧值 → 新值 → 目的”。 - 角色 Prefab 只挂通用组件,不在 Prefab 上复制核心战斗脚本。 > **编辑器工具优先级** > > 最值得做的自定义工具是“招式时间轴 + HitBox/HurtBox 轨迹预览”。它应支持拖动 Tick、复制帧、镜像判定、显示动画参考姿态并即时运行单招测试。 **MATCH & UI** # 14 UI、回合流程与设置 ## 14.1 MatchFlow 状态 | **状态** | **持续 / 退出条件** | **允许内容** | |-----------------|-------------------------|--------------------------------| | **Loading** | 资源准备完成 | 不推进战斗 | | **Intro** | 角色入场动画结束 | 镜头演出、不可操作 | | **RoundReady** | “Round / Fight”演出结束 | 角色锁定、计时不动 | | **Fighting** | KO 或时间归零 | 完整战斗逻辑 | | **KOFreeze** | 短暂停顿结束 | 命中表现继续,禁止新输入 | | **RoundResult** | 胜负演出完成 | 更新局数、播放胜利动作 | | **MatchResult** | 玩家选择重开或退出 | 结果 UI | | **Paused** | 关闭暂停 | BattleTime 停止,RealTime 继续 | ## 14.2 战斗 HUD - 双方生命条:显示当前值、延迟损失值(白血)与 KO 状态。 - 双方能量条:0–100;满能量时有明确但不过度闪烁的提示。 - 回合标记:最多 2 个胜利点;当前回合和剩余时间居中。 - 连击与提示:Combo、Counter、Punish、Block;由 Domain Event 驱动。 - 训练/调试叠层:当前状态、MoveId、招式帧、帧优势、输入历史和判定框开关。 ## 14.3 设置与可访问性 | **类别** | **设置项** | |----------|---------------------------------------------------| | **控制** | 键盘/手柄重绑定、摇杆死区、输入显示、简易指令开关 | | **画面** | 分辨率、窗口模式、画质、动态模糊关闭、闪光强度 | | **镜头** | 震屏强度、超杀镜头、镜头跟随强度 | | **音频** | 总音量、音乐、音效、语音、手柄震动 | | **游戏** | 回合数、时间、AI 难度、训练模式生命恢复 | | **辅助** | 色盲友好 HUD、字幕、慢速训练、按键提示 | > **UI 数据边界** > > HUD 只读取 BattleSnapshot,不直接持有 FighterController。这样暂停、回放、观战与未来联网时都可以复用同一套展示逻辑。 **AI & TRAINING** # 15 AI 与训练木桩 ## 15.1 MVP AI 结构 采用“感知 + 战术状态 + 效用评分”的轻量 AI。AI 不需要直接读取未来输入或命中结果;它只使用当前距离、双方状态、资源、角落位置和近期行为。决策间隔建议 4–8 Tick,并加入反应延迟。 | **战术状态** | **进入条件** | **候选行为** | |--------------|-------------------------|--------------------------------------| | **Neutral** | 双方可行动、距离中远 | 走位、能量弹、试探重脚、等待 | | **Approach** | 距离过远或时间落后 | 前走、前跳、突进技 | | **Pressure** | 对手在 BlockStun / 角落 | 轻攻击、延迟重击、必杀取消、后退诱骗 | | **Defense** | 对手起攻或自身低血量 | 格挡、后退、对空、无敌技 | | **Punish** | 检测到对手大收招 | 选择起手足够快且距离可达的招式 | | **Combo** | 己方攻击命中确认 | 按预设连段脚本执行后续输入 | ## 15.2 难度差异 | **维度** | **简单** | **普通** | **困难** | |--------------|----------------|------------------|------------------------| | **反应延迟** | 18–24 Tick | 10–16 Tick | 6–10 Tick | | **指令失误** | 较高 | 中等 | 低 | | **格挡倾向** | 只格挡明显攻击 | 按距离与动作判断 | 能识别常见高低段 | | **连段长度** | 1–2 击 | 3–4 击 | 4–6 击并使用资源 | | **反制知识** | 无 | 有限对空/惩罚 | 基于帧差和距离选择惩罚 | | **随机性** | 高 | 中 | 低但仍保留风格权重 | ## 15.3 训练木桩 - 站立、蹲下、跳跃、第一击后格挡、随机格挡。 - 受击后恢复生命、能量固定、位置重置。 - 录制 5–10 秒输入并循环播放,用于测试防守与惩罚。 - 显示连击伤害、起始伤害、缩放、帧优势和可行动 Tick。 - 一键重置到舞台中央或角落。 > **禁止“读心”** > > 困难 AI 可以更快、更准,但不应读取玩家尚未生效的输入,也不应在 0 Tick 内完美反应。可接受的优势来自更短反应延迟、更好的距离判断与更完整的连段脚本。 **PERFORMANCE & FUTURE** # 16 性能、回放与联机预留 ## 16.1 性能预算 | **项目** | **目标** | |----------------|----------------------------------------------------------| | **战斗 Tick** | 平均 \< 1.5 ms,99 分位 \< 3 ms(双角色 + 常规飞行道具) | | **碰撞判定体** | 每角色 HurtBox 4–8 个;单招 HitBox 1–4 个 | | **运行时分配** | 战斗关键路径 0 B / Tick;列表和事件缓冲预分配 | | **飞行道具** | 常规同时存在 ≤ 16;使用对象池 | | **VFX / 飘字** | 对象池 + 最大并发;超限时降级而非阻塞 | | **动画** | 避免每 Tick 字符串查找;缓存哈希与状态 ID | ## 16.2 回放 首版回放只需保存初始随机种子、角色/场景数据版本与每 Tick 的 InputFrame。回放时重新运行战斗逻辑,并周期性记录状态哈希。若哈希不一致,立即输出首个分歧 Tick、角色状态、位置、生命与当前招式。 - 回放文件不保存动画、特效或音频状态。 - 每 60 Tick 记录一次轻量状态哈希,用于自动检测非确定性。 - 版本不兼容时明确拒绝播放,不尝试静默修复。 - Bug 报告可自动附带最近 10 秒输入与 CombatLog。 ## 16.3 回滚联机预留 MVP 不实现联网,但核心域应避免阻断未来回滚:战斗逻辑固定 Tick、输入驱动、状态可序列化、表现层可重建。真正接入网络时,需进一步处理浮点确定性、快照大小、回滚重演性能与输入延迟。 | **现在就做** | **以后再做** | |---------------------------------------|------------------------------| | 固定 Tick、输入帧、战斗快照、状态哈希 | 网络传输、预测输入、回滚窗口 | | 战斗域不依赖场景查找与动画事件 | 跨平台确定性与浮点策略 | | 表现事件带唯一 ID,允许回滚撤销/去重 | 观战、断线重连、匹配与反作弊 | | 对象池和可重建飞行道具 | 网络带宽压缩与同步协议 | > **现实边界** > > 不要为了“以后可能联网”过早引入复杂框架。只要保持固定 Tick、输入驱动、数据可序列化和表现解耦,单机原型就已经保留了最有价值的联机基础。 **DEBUGGING** # 17 调试工具与可观测性 ## 17.1 必做工具 | **工具** | **功能** | **验收标准** | |-------------------|--------------------------------------|--------------------------------| | **帧步进** | 暂停后每次推进 1 Tick / 10 Tick | 状态、动画采样和判定体同步推进 | | **输入历史** | 显示最近 30–60 Tick 的方向和按键 | 标出已消费输入与指令匹配区间 | | **判定框显示** | Hit/Hurt/Push Box 颜色区分 | 镜像、缩放和移动后仍准确 | | **招式面板** | MoveId、当前帧、阶段、取消窗口 | 能看到有效 HitBox 与无敌窗口 | | **战斗日志** | 命中候选、过滤原因、HitResult | 可按角色、招式与 Tick 筛选 | | **状态快照** | 位置、速度、状态、生命、能量、Facing | 一键复制为文本用于 Bug 单 | | **输入录制/回放** | 录制并重复执行短序列 | 多次播放结果哈希一致 | ## 17.2 CombatLog 示例 **命中日志应能回答“为什么发生这个结果”** ```text T=1842 P1 move=st_hp frame=8 phase=Active candidate: hitbox=body_0 target=P2 hurtbox=torso guardIntent=true stance=Standing hitLevel=Mid => BLOCK result: blockStun=14 hitStop=8 guardPush=(0.42,0) meter: P1 +4, P2 +2 transition: P2 -> BlockStun(14), P1 stays st_hp frame=8 ``` ## 17.3 自动监控断言 - 角色生命、能量与状态枚举始终在合法范围。 - 同一 Fighter 同 Tick 只能提交一个最终状态转移。 - MoveController 帧不得超出总帧数;已结束招式必须释放 MoveInstance。 - 同一 HitGroup 不得在禁止重击间隔内重复命中同一目标。 - KO 后不得接受玩家输入或生成新的攻击 HitBox。 - 角色逻辑位置不得离开舞台边界,Z 逻辑坐标必须为 0。 - 回放状态哈希不一致时自动中止并导出差异。 > **调试不是“开发者模式装饰”** > > 格斗游戏的大多数问题都发生在特定 Tick 和特定状态组合。没有输入历史、帧步进和判定框,团队会把时间花在猜测而不是定位。 **DELIVERY PLAN** # 18 开发里程碑与任务拆分 以下计划以 1 名程序 + 1 名通才美术/动画的原型团队为参考。若是个人开发,可按同一顺序推进,但不要并行制作大量内容。每个阶段必须通过验收门再进入下一阶段。 | **阶段** | **主要交付** | **验收门** | |-------------------|-------------------------------------------------|--------------------------------------------------| | **M0 工程骨架** | BattleClock、输入帧、基础数据、空场景、调试面板 | 帧步进与输入历史可用;固定 Tick 不受渲染帧率影响 | | **M1 运动原型** | 双角色生成、行走、转身、跳跃、PushBox、镜头 | 无穿透、无越界;30/60/120 FPS 手感一致 | | **M2 命中闭环** | 普通技、Hit/Hurt Box、HitStop、受击、格挡、KO | 镜像角色能完成一局;结果可由 CombatLog 解释 | | **M3 招式系统** | 指令识别、取消、飞行道具、对空、突进、超杀 | 录制输入可稳定触发;资源和多段命中正确 | | **M4 比赛产品化** | HUD、回合流程、暂停、设置、本地双人、训练木桩 | 从启动到重开无阻断;关键设置可保存 | | **M5 AI 与打磨** | AI、VFX/SFX、镜头、两角色内容、性能优化 | 完整 Demo 可连续游玩 30 分钟无卡死或明显漏判 | | **M6 发布准备** | 测试回归、手柄覆盖、打包、日志与崩溃信息 | 验收清单全绿;已知问题有明确说明 | ## 18.1 工作量粗估 | **模块** | **人日范围** | **备注** | |--------------------------|--------------|-----------------------------------------------------| | **战斗核心与调试** | 8–12 | 输入、时钟、状态机、运动、判定、命中与工具 | | **普通技 / 必杀 / 超杀** | 5–8 | 不含高质量动画制作 | | **比赛流程与 UI** | 3–5 | 基础 HUD、设置、回合与暂停 | | **AI 与训练模式** | 3–5 | 简单效用 AI + 训练木桩 | | **表现整合** | 5–8 | 动画接入、特效、音效、镜头与反馈 | | **测试与优化** | 4–7 | 自动测试、性能、手柄、打包与回归 | | **合计** | 28–45 | 占位素材的功能型 Demo;个人开发按技能和素材情况浮动 | ## 18.2 推荐任务拆分 - 每个功能任务都包含:数据、运行时、调试显示、测试场景与验收用例。 - 角色动作与判定由同一 MoveId 串联,避免动画名、招式名和代码枚举不一致。 - 每新增一个招式,必须同时提交帧表、HitboxTrack、命中/格挡结果和训练模式验证步骤。 - 每次调整核心结算顺序,都运行固定回放集并比较状态哈希。 - 表现任务在战斗事件稳定后接入,不直接修改战斗核心以“配合动画”。 > **第一可玩顺序** > > Idle → Walk → Jump → 一个普通技 → HitBox/HurtBox → HitStop/HitStun → Block → KO。完成这条链路前,不做超杀镜头、AI 或复杂 UI。 **QA** # 19 测试方案与验收标准 ## 19.1 自动测试层级 | **层级** | **覆盖内容** | **示例** | |-------------------|-----------------|-----------------------------------------------| | **Unit** | 纯算法与数据 | 指令匹配、伤害缩放、格挡段位、优先级排序 | | **Simulation** | 无渲染战斗 Tick | 固定输入运行 600 Tick,检查状态哈希与最终生命 | | **PlayMode** | 场景与组件集成 | 跳跃接地、舞台边界、飞行道具回收、HUD 更新 | | **Golden Replay** | 回归回放集 | 10–30 条已知战斗录像在每次构建中重放 | | **Manual** | 手感与设备 | 键盘/多种手柄、帧率、震屏、视觉可读性 | ## 19.2 核心验收用例 | **ID** | **场景** | **通过标准** | |------------|-------------------------------|------------------------------------------| | **MOV-01** | 前后行走并互相推挤 | 不穿透、不抖动、不越界;角落分摊正确 | | **MOV-02** | 30/60/120 FPS 下连续跳跃 | 起跳高度、滞空 Tick 与落点一致 | | **INP-01** | 快速输入 236+P | 在宽容窗口内稳定触发,超窗不触发 | | **INP-02** | 236236+P 且能量不足 | 不吞键;按优先级回退到合法动作 | | **ATK-01** | 轻拳命中站立对手 | 伤害、HitStop、HitStun、推远与特效一致 | | **BLK-01** | 站防高/中/低段 | 高/中成功,低段失败并进入受击 | | **BLK-02** | 蹲防高/中/低段 | 中/低成功,高段失败并进入受击 | | **HIT-01** | 双方同 Tick 普通攻击 | 按交易规则双方受击,日志顺序稳定 | | **HIT-02** | 多 HurtBox 与一个 HitBox 重叠 | 只结算一次,命中点选择一致 | | **SP-01** | 飞行道具命中/格挡/出界 | 三种路径均正确回收且无重复命中 | | **SP-02** | 对空技无敌窗口 | 窗口内忽略指定攻击,窗口外正常受击 | | **SU-01** | 满能量超杀 | 只扣一次资源;冻结、镜头、多段与终结正确 | | **KO-01** | 同 Tick 生命归零与多段后续 | 只结算合法段;进入 KO 后无新攻击 | | **REP-01** | 同输入回放 20 次 | 最终状态与中间哈希完全一致 | ## 19.3 功能完成定义(Definition of Done) - 设计数据已填写且通过合法性校验,没有魔法数字散落在运行时代码。 - 功能可在 Debug HUD 中观察关键状态与 Tick。 - 至少有 1 个自动测试或固定回放覆盖主要逻辑。 - 键盘与至少一种手柄可用,重绑定后仍正常。 - 30/60/120 FPS 下结果一致;暂停、慢动作与 HitStop 不影响输入匹配。 - 不存在已知的状态卡死、重复命中、越界、资源重复扣除或 KO 后继续行动。 - 表现层缺失时战斗逻辑仍可完整运行;表现对象销毁不会破坏比赛。 > **发布门槛** > > 完整对战连续运行 30 分钟,无崩溃、无永久卡死、无明显输入丢失;核心回放集全部通过;关键路径战斗 Tick 在目标机器上满足性能预算。 **RISKS & APPENDIX** # 20 风险、原创边界与附录 ## 20.1 主要风险与缓解 | **风险** | **表现** | **缓解措施** | |------------------|------------------------------------------|------------------------------------------| | **动画驱动逻辑** | 判定漏发、过渡不同步、改动画导致规则变化 | 逻辑帧表权威;动画只采样与展示 | | **范围持续膨胀** | 投技、防反、联网、角色内容同时开工 | 严格按 M0–M6 验收门推进 | | **输入手感差** | 指令过严或误触发,玩家无法稳定出招 | 输入录制、匹配日志、可配置宽容窗口 | | **判定难调** | 动画好看但判定不稳定或不可读 | 独立 HitboxTrack 编辑器与帧步进 | | **碰撞不确定** | 动态刚体、回调顺序导致同帧结果变化 | 运动学控制 + 收集后统一结算 | | **表现反向侵入** | 镜头/特效脚本改生命或状态 | Domain / Presentation 事件边界与代码审查 | | **内容制作成本** | 每个招式需要动作、判定、特效、音效 | 先做少量高辨识度招式,复用事件模板 | | **知识产权风险** | 造型、动作、招式名和 UI 过度相似 | 建立原创设定与视觉语言;保留素材来源记录 | ## 20.2 原创边界检查 - 不要直接使用现有格斗游戏的角色姓名、服装轮廓、招式名称、语音、UI、标志或特效图样。 - 通用机制如走、跳、格挡、飞行道具、对空、能量槽和超杀冻结可以采用,但表达方式应原创。 - 动作捕捉、音效、字体、模型与特效包需确认商业许可范围,并保存许可证与购买凭证。 - 宣传文案使用“2.5D 对战格斗”描述,不以他人商标作为产品名称或核心卖点。 ## 附录 A:首个灰盒角色帧表示例 | **招式** | **输入** | **起/持/收** | **伤害** | **硬直 H/B** | **用途** | |--------------|----------|------------------|----------|--------------|----------------------------| | **站轻拳** | LP | 4 / 2 / 8 | 40 | 10 / 7 | 近身确认;命中可取消必杀 | | **站重拳** | HP | 9 / 3 / 18 | 90 | 16 / 12 | 重击;部分帧可对空 | | **站轻脚** | LK | 5 / 3 / 10 | 45 | 11 / 8 | 中距离试探 | | **站重脚** | HK | 11 / 3 / 22 | 105 | 18 / 14 | 长距离;反击风险高 | | **蹲轻脚** | 2+LK | 5 / 2 / 9 | 35 | 9 / 7 | 低段;可链轻拳 | | **跳重脚** | 空中 HK | 7 / 5 / 着地6 | 80 | 14 / 11 | 跳入攻击 | | **能量弹** | 236+P | 12 / 投射物 / 22 | 80 | 15 / 12 | 远程牵制;削血 8 | | **对空升击** | 623+P | 5 / 6 / 28 | 110 | 击倒 / 15 | 1–6 Tick 上半身无敌 | | **突进踢** | 214+K | 10 / 5 / 20 | 100 | 17 / 13 | 接近与连段收尾 | | **超必杀** | 236236+P | 7 / 多段 / 35 | 300 | 击倒 / 20 | 消耗 100;起手冻结 10 Tick | *H/B = HitStun / BlockStun。所有数值仅为原型起点,不代表最终平衡。* ## 附录 B:首轮实现清单 | **完成** | **任务** | **完成** | **任务** | |----------|----------------------------------------|----------|----------------------------------------------| | □ | BattleClock 与 60 Tick 主循环 | □ | InputBuffer 与方向相对化 | | □ | CommandRecognizer 与输入日志 | □ | FighterStateMachine 与转移优先级 | | □ | FighterMotor、跳跃、舞台边界与 PushBox | □ | MoveData、MoveTimeline 与取消窗口 | | □ | HitBox/HurtBox 轨迹与调试显示 | □ | HitResolver、格挡、伤害、HitStop、硬直与击退 | | □ | 飞行道具、对空技、突进技与超必杀 | □ | MatchFlow、HUD、KO、暂停与重开 | | □ | 训练木桩、AI、输入回放与状态哈希 | □ | 动画、VFX、SFX、镜头与可访问性设置 | ## 附录 C:项目启动时的 10 个决定 > **1.** 确认战斗是严格 2D 平面,还是允许 Z 轴闪避;本方案默认严格 2D。 > > **2.** 确认普通技数量与按钮数;本方案默认 4 攻击键。 > > **3.** 确认格挡采用背向方向,是否提供独立 Guard 辅助键。 > > **4.** 确认是否支持蹲姿与高低段;本方案建议首版支持。 > > **5.** 确认每角色必杀技与超杀数量;本方案为 3 + 1。 > > **6.** 确认是否有动态刚体需求;战斗角色默认不使用动态刚体。 > > **7.** 确认首版仅单机/本地对战,不在 MVP 中实现联网。 > > **8.** 确认动画与模型来源、许可和可用动作数量。 > > **9.** 确认调试工具必须随核心功能同步交付。 > > **10.** 确认第一可玩验收后再投入完整美术与角色内容。 > **最终建议** > > 先做一个角色镜像对战,完整打通“一次输入 → 一个动作 → 一个判定 → 一次命中/格挡 → 一次状态恢复 → 一次 KO”。这条链路稳定后,新增角色与招式才会变成可控的内容生产,而不是继续堆技术债。