鸟语天空
游戏AI状态机
post by:追风剑情 2021-11-29 15:46

一、工程截图

111111.png222222.png

AIState.cs

using System;
/// <summary>
/// AI状态基类
/// </summary>
public class AIState
{
    //状态ID
    public virtual int StateId { get { return -1; } set { } }
    // 进入状态
    public virtual void Enter(Enum previousState, params object[] args) { }
    public virtual void Enter(int previousStateId, object p) { }
    // 更新状态
    public virtual void Update() { }
    // 退出状态
    public virtual void Exit() { }
    // 动画事件
    public virtual void OnAnimationEvent(string p) { }
    // 销毁
    public virtual void Dispose() { }
    //检测完成条件(对于并行任务,需要同时检测)
    public virtual void CheckCompletionCondition() { }
    //是否完成(true: CheckCompletionCondition()方法将不会被调用,否则会每帧调用)
    public virtual bool IsCompleted { get; set; } = true;
    //转换状态
    public virtual AIStateMachine.TransformParams TransformState() { return null; }
}

AIStateMachine.cs

using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// AI状态机
/// </summary>
public class AIStateMachine
{
    private Dictionary<int, AIState> stateDic = new Dictionary<int, AIState>();
    private AIState currentState;
    private TransformParams nextStateParam = null;

    //转换参数
    public class TransformParams
    {
        public int nextStateId;
        public object p;
    }

    //添加状态
    public void Add(int id, AIState state)
    {
        if (stateDic.ContainsKey(id))
        {
            Debug.LogErrorFormat("[AIStateMachine] state id({0}) already exist.", id);
            return;
        }
        stateDic.Add(id, state);
    }

    //移除状态
    public void Remove(int id)
    {
        if (stateDic.ContainsKey(id))
            stateDic.Remove(id);
    }

    //动画事件
    public void OnAnimationEvent(string p) 
    {
        if (currentState != null)
            currentState.OnAnimationEvent(p);
    }

    //转换状态
    public void ChangeState(int id, object p=null)
    {
        if (!stateDic.ContainsKey(id))
        {
            Debug.LogErrorFormat("[AIStateMachine] Not found state by id({0})", id);
            return;
        }
        int preStateId = currentState != null ? currentState.StateId : -1;
        currentState?.Exit();
        currentState = stateDic[id];
        currentState.Enter(preStateId, p);
    }

    private void ChangeState(TransformParams tp)
    {
        ChangeState(tp.nextStateId, tp.p);
    }

    //状态机的驱动函数,需要每帧调用。
    public void Tick()
    {
        if (currentState == null)
            return;

        if (nextStateParam != null)
        {
            ChangeState(nextStateParam);
            nextStateParam = null;
            return;
        }

        nextStateParam = currentState.TransformState();
        if (nextStateParam != null)
            return;
        currentState.Update();

        //检测各状态完成条件
        foreach(var state in stateDic.Values)
        {
            if (!state.IsCompleted)
                state.CheckCompletionCondition();
        }
    }

    //释放
    public void Dispose()
    {
        currentState = null;
        nextStateParam = null;
        foreach (var state in stateDic.Values)
            state.Dispose();
        stateDic.Clear();
    }
}

ActionStateEnum.cs

namespace AI.Player
{
    /// <summary>
    /// 状态枚举
    /// </summary>
    public enum ActionStateEnum
    {
        None,
        Idle,    //待机
        Goto,    //前往目的地
        TalkNPC, //NPC对话
    }
}

评论:
发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容