AI模块(有限状态机、行为树)-应用在cocos中

前言:

本模块是在cocos项目中运用战斗框架,根据学习别人的文章来结合项目进行编写的,若有不对不合理的地方有劳大家指正,万分感谢!!!若有能有用的上的,万分荣幸!

简介:

AI模块一般是对怪物的AI实现,或者托管等自动战斗的情况。具体方式可能根据项目的具体需求来选择,常用的有:有限状态机,行为树。

有限状态机(fsm)

介绍:

状态机,或称有限状态机FSM(Finite State Machine),是一种重要的编程思想。

状态机有3要素:状态事件响应

  • 状态:系统处在什么状态?
  • 事件:发生了什么事?
  • 响应:此状态下发生了这样的事,系统要如何处理?

状态机有三大特征:

  • 状态总数(state)是有限的。
  • 任一时刻,只处在一种状态之中。
  • 某种条件下,会从一种状态转变(transition)到另一种状态。

下面用在Cocos项目中的例子来做个简单的应用:

各个状态均包含以下操作:

export interface IState{
    OnEnter();//进入状态机回调
    OnExit();//退出状态机回调
    OnUpdate(deltaTime);//持续执行状态
    //OnCheck();
    //OnFixdeUpdate();
}

定义对应状态:

export enum StateType{
    //状态机中可能的状态
    /**未激活 */
    InActive, 
    /**等待游戏开始 */          
    WaitingStart,
    /**待机 */
    Idle,
    /**待机 */
    Idle_TowerDefense,
    /**移动 */
    Move,
    /**攻击 */
    Attack,
    /**正在大杀特杀 */
    Killing,
    /**死亡中 */
    Die,
    /**怪物扮演中的玩家 */
    MonsterCosplay,
    /**显示结算界面 */
    END,
}

定义状态机:

@ccclass('FSM')
export class FSM{
    public curState:IState;
    public states = new Map<StateType,IState>;
    public blackboard:BlackBoard;

    public constructor(blackboard:BlackBoard){
        this.states = new Map<StateType,IState>();
        this.blackboard = blackboard;
    }

    /**增加对应状态 */
    public AddState(stateType:StateType,state:IState){
        if(this.states.has(stateType)){
            return;
        }
        this.states.set(stateType,state);
    }

    /**切换到对应状态 */
    public SwitchState(stateType:StateType){
        if(!this.states.has(stateType)){
            return;
        }
        if(this.curState != null){
            this.curState.OnExit();
        }
        this.curState = this.states.get(stateType);
        this.curState.OnEnter();
    }

    /**获取到对应状态 */
    public GetIState(stateType:StateType){
        return this.states.get(stateType);
    }

    /**这里实现状态机对应执行逻辑 */
    public OnUpdate(deltaTime){
        this.curState?.OnUpdate(deltaTime);
    }

    // public OnCheck(){
    //     this.curState.OnCheck();
    // }

    // public OnFixedUpdate(){
    //     this.curState.OnFixedUpdate();
    // }

}

定义AI角色状态,并初始化状态机(根据自己的逻辑来切换对应状态):

//初始化状态机
@ccclass('Test')
export class Test extends AttrBase {
    public fsm: FSM;
    public blackboard: TestBlackboard = new TestBlackboard();//此处存储共享数据,或者向外展示的数据,可配置的数据

    InitFsm() {
        this.fsm = new FSM(this.blackboard);
        /**攻击状态 */
        this.fsm.AddState(StateType.Attack, new AttackState(this.fsm));
        /**增加待机状态 */
        this.fsm.AddState(StateType.Idle, new IdleState(this.fsm));
        /**增加死亡状态 */
        this.fsm.AddState(StateType.Die, new DieState(this.fsm));
        /**增加等待开始状态 */
        this.fsm.AddState(StateType.WaitingStart, new WaittingState(this.fsm));
        /**增加结束状态 */
        this.fsm.AddState(StateType.END, new ENDState(this.fsm));
    }
    Init(){
        super.Init();
        this.InitFsm();
        this.fsm.SwitchState(StateType.WaitingStart);//切换状态为游戏开始状态
    }
}

//定义各个状态
class WaittingState implements IState {
    private fsm: FSM;
    public blackboard: TestBlackboard;
    public constructor(fsm: FSM) {
        this.fsm = fsm;
        this.blackboard = fsm.blackboard as TestBlackboard;
    }

    //新开局初始化
    OnEnter() {
    }
    OnExit() {
    }

    OnUpdate(deltaTime: number) {
        if(GamePlaying){//游戏开始
            this.fsm.SwitchState(StateType.Idle);//切换状态IDLE
        }
    }
}

行为树(这里没有太深入的研究,应用的也不太多,大概了解了下理论)

简介:

行为树(Behavior Tree)是一种用于描述复杂行为逻辑的图形化结构,常用于游戏开发、机器人控制、人工智能等领域。它由节点组成,节点之间通过连接线连接,形成树状结构。行为树主要由以下几种类型的节点组成:

  • 行为节点(Action Nodes):执行具体的动作或任务,例如移动、攻击、待机等。
  • 条件节点(Conditional Nodes):判断条件是否满足,通常用于控制流程的分支。
  • 复合节点(Composite Nodes):用于组合和控制其他节点的执行顺序和逻辑关系,主要分为序列节点和选择节点两种类型:
    • 序列节点(Sequence Nodes):按顺序执行其子节点,只有当所有子节点都成功执行时,序列节点才会返回成功;一旦有一个子节点失败,则序列节点会立即返回失败,不再执行后续节点。
    • 选择节点(Selector Nodes):按顺序尝试执行其子节点,一旦某个子节点成功执行,选择节点即返回成功;只有当所有子节点都失败时,选择节点才会返回失败。
  • 装饰节点(Decorator Nodes):用于修改其子节点的行为或结果,常见的装饰节点包括反转节点、条件节点、超时节点等。

简单的代码运用

    private actionType: number = 0;
    public get ActionType(): number { return this.actionType; }
    /**玩家的行为:0为待机,1为移动,2为跳,3为跑,4为散步,9为濒死,10为死亡 */
    public set ActionType(value: number) {
        switch (value) {
            case 0:
            case 9:
                this.ChangeAni("idle", true);
                break;
            case 2:
                break;
            case 1:
            case 3:
            case 4:
                this.ChangeAni("run", true);
                break;
            case 5:
            case 6:
            case 7:
            case 8:
                break;
            case 10:
                this.ChangeAni("die",false);
                break;
            default:
                Logger.Error("Character ActionType Error: " + value);
                break;
        }
        this.actionType = value;
    }
    
    ChangeAni(aniName: string, isLoop: boolean, func?){
        //定义自己的对应逻辑
    }

参考文章:

如何深入理解“有限状态机”的设计思想? - 知乎 (zhihu.com)

JavaScript与有限状态机 - 阮一峰的网络日志 (ruanyifeng.com)

ChatGpt的回答

posted @   千裳~  阅读(443)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示