Game_Num_Basics_And_Calc

🤖 有限状态机 (FSM) 设计与实战指南

文档目标: 详解 Vampirefall 中 AI 行为的核心驱动逻辑。 适用对象: 怪物 AI、防御塔逻辑、Boss 阶段转换。


1. 🧠 FSM 核心概念 (The Basics)

有限状态机由三个要素组成:

  1. 状态 (State): 角色当前在做什么? (e.g., Idle, Chase, Attack)
  2. 转换 (Transition): 什么条件下切换到另一个状态? (e.g., Distance < 5m -> 切换到 Attack)
  3. 行为 (Action): 进入/退出/保持该状态时做什么? (e.g., OnEnter: 播放吼叫动画)

2. 👹 怪物 AI 状态机 (Monster FSM)

混合品类游戏的怪物 AI 比传统塔防更复杂,因为它需要处理“仇恨切换”。

2.1 状态流转图 (State Graph)

graph TD
    Spawn(出生) -->|落地动画结束| Move(寻路移动)
    Move -->|遇到路障| Breach(拆墙/塔)
    Move -->|被玩家攻击/嘲讽| Aggro(仇恨追击)
    Aggro -->|距离过远/超时| Move
    Aggro -->|进入攻击范围| Attack(攻击)
    Breach -->|塔被摧毁| Move
    Attack -->|目标死亡| Move
    Attack -->|攻击后摇结束| Cooldown(对峙/调整)
    Cooldown -->|CD结束| Attack

2.2 关键状态详解

A. State_Move (寻路移动)

B. State_Breach (拆墙)

C. State_Aggro (仇恨/追击)

2.3 📁 普通怪物实战案例 (Minion Examples)

结合游戏特色,我们定义两种极端的怪物 AI 模板。

案例 A: 骷髅工兵 (Skeleton Sapper) - 绝对攻城型

案例 B: 幽灵刺客 (Ghost Assassin) - 风筝/切后排型


3. 👑 Boss 战斗状态机 (Boss FSM)

Boss 不仅仅是血厚的怪,它是一个带有剧本的流程。我们需要引入 “Phase System” (阶段系统)

3.1 阶段转换流转图

Boss 的 FSM 是分层的:上层管理阶段,下层管理具体行为。

graph TD
    Intro(登场演出) --> Phase1
    Phase1 -->|HP < 60%| Transition1(转阶段/无敌)
    Transition1 --> Phase2
    Phase2 -->|HP < 20%| Transition2(狂暴前摇)
    Transition2 --> Phase3(软狂暴/Rage)
    Phase3 --> Dead

3.2 实战案例:鲜血领主 (Vampire Lord)

Phase 1: 优雅剑术 (100% - 60% HP)

Transition 1: 鲜血盛宴 (机制检测)

Phase 2: 魔法轰炸 (60% - 20% HP)

Phase 3: 困兽之斗 (20% - 0% HP)


4. 🗼 防御塔状态机 (Tower FSM)

塔的逻辑相对简单,重点在于“索敌效率”和“状态重置”。

3.1 状态流转图

graph TD
    Idle(待机扫描) -->|发现敌人| Warmup(预热/瞄准)
    Warmup -->|预热完成| Fire(开火)
    Fire -->|开火结束| Cooldown(冷却/装填)
    Cooldown -->|CD结束 & 有敌人| Fire
    Cooldown -->|CD结束 & 无敌人| Idle
    Fire -->|目标死亡/丢失| Idle

3.2 关键状态详解

A. State_Idle (待机扫描)

B. State_Warmup (预热/瞄准)

C. State_Fire (开火)


4. 💻 代码实战:轻量级 FSM 框架 (No-GC)

不要用复杂的类继承 (Class-based States) 来做成千上万的小怪,那样内存开销太大。 推荐使用 Enum + Switch (简单怪) 或 Struct-based FSM (复杂怪)。

4.1 方案 A: 极简版 (适合小怪/塔)

public enum EState { Idle, Move, Attack, Dead }

public class SimpleMonster : MonoBehaviour {
    private EState _currentState;
    private float _stateTimer;

    void Update() {
        // 状态机驱动
        switch (_currentState) {
            case EState.Move: UpdateMove(); break;
            case EState.Attack: UpdateAttack(); break;
        }
    }

    void ChangeState(EState newState) {
        OnExit(_currentState);
        _currentState = newState;
        _stateTimer = 0;
        OnEnter(newState);
    }
    
    // ... 具体逻辑写在函数里
}

4.2 方案 B: 结构化版 (适合 Boss/玩家)

如果你嫌 Switch 太乱,可以用轻量级的类封装,但要避免每帧 new

// 1. 定义状态基类
public abstract class BaseState {
    protected BossController _boss;
    public BaseState(BossController boss) { _boss = boss; }
    public abstract void OnEnter();
    public abstract void OnUpdate();
    public abstract void OnExit();
}

// 2. 状态机控制器
public class StateMachine {
    private BaseState _current;
    
    public void ChangeState(BaseState newState) {
        _current?.OnExit();
        _current = newState;
        _current?.OnEnter();
    }
    
    public void Update() {
        _current?.OnUpdate();
    }
}

// 3. 具体状态实现
public class BossChaseState : BaseState {
    public override void OnUpdate() {
        if (_boss.DistanceToPlayer < 2.0f) {
            _boss.FSM.ChangeState(_boss.StateAttack); // 预先创建好的实例,不要 new!
        }
    }
}

5. 🎓 实用建议与坑

5.1 🚫 避免 “Ping-Pong” (状态乒乓)

5.2 🌍 全局状态 (Global State)

5.3 🎞️ 动画状态机 (Animator) vs 逻辑状态机 (Logic FSM)