简易行为树

作者: APP4x | 来源:发表于2020-09-16 21:49 被阅读0次

    行为树(Behavior Tree)
    是一棵用于控制AI决策行为的、包含了层级节点的树结构

    主要就是:
    用树的结构解决状态切换判断问题的

    那咋解决呢?
    用这颗树,自顶向下的,通过某些条件来搜索这棵树,最终确定需要做的行为(叶子结点),并且执行它

    好处是啥呢?
    可以定好很多抽象行为,不用理会战斗中距离发生了什么

    那就实现一个简易的行为树:

    1.首先定义一个 BasicNode.cs 类,表示所有结点的基类
    主要的功能:
    a.控制结点的生命周期
    b.Tick出结果
    c.设置父节点

    public enum EBehaviorStatus
        {
            None,
            Success,
            Fail,
            Interrupt
        }
    
        public class BasicNode
        {
            public virtual EBehaviorStatus Tick()
            {
                return EBehaviorStatus.Success;
            }
    
            public virtual void SetParent()
            {
                //这里写添加子节点的方法
            }
    
            public virtual void OnInit()
            {
            }
    
            public virtual void OnSetData(params int[] data)
            {
            }
    
            public virtual void CleanNode()
            {
                //这里写清理子节点的方法
            }
        }
    

    2.抽象出几个基础结点
    a.LoopNode:没有错就一直执行

    public class LoopNode : BasicNode
    {
        public int m_Loop = 0;
        //private int m_Recycle = 0;
        public override EBehaviorStatus Tick()
        {
            for (int recycle = 0; recycle < m_Loop; recycle++)
            {
                for (int i = 0; i < m_ChildList.Count; i++)
                {
                    BasicNode node = m_ChildList[i];
                    EBehaviorStatus status = node.Tick();
                    if (status == EBehaviorStatus.Fail || status == EBehaviorStatus.Interrupt)
                    {
                        return EBehaviorStatus.Interrupt;
                    }
                }
            }
            return EBehaviorStatus.Success;
        }
    }
    

    b.NegationNode:指定结点

    public class NegationNode : BasicNode
    {
        private BasicNode m_RealNode;
    
        public void SetNode(BasicNode node)
        {
            m_RealNode = node;
        }
        public EBehaviorStatus Tick()
        {
            if (m_RealNode != null)
            {
                EBehaviorStatus status = m_RealNode.Tick();
                if (status == EBehaviorStatus.Success || status == EBehaviorStatus.Interrupt)
                {
                    return EBehaviorStatus.Fail;
                }
                else
                {
                    return EBehaviorStatus.Success;
                }
            }
            else
            {
                return EBehaviorStatus.Success;
            }
        }
    }
    

    c.SelectorNode:选择一个,有一个成功就返回

    public class SelectorNode : BasicNode
    {
        public override EBehaviorStatus Tick()
        {
            for (int i = 0; i < m_ChildList.Count; i++)
            {
                BasicNode node = m_ChildList[i];
                EBehaviorStatus status = node.Tick();
                if (status == EBehaviorStatus.Success)
                {
                    return EBehaviorStatus.Success;
                }
                else if (status == EBehaviorStatus.Interrupt)
                {
                    return EBehaviorStatus.Interrupt;
                }
            }
            return EBehaviorStatus.Fail;
        }
    }
    

    d.SequenceNode:按顺序依次执行,有一个失败就返回

    public class SequenceNode : BasicNode
    {
        public override EBehaviorStatus Tick()
        {
            for (int i = 0; i < m_ChildList.Count; i++)
            {
                BasicNode node = m_ChildList[i];
                EBehaviorStatus status = node.Tick();
                if (status == EBehaviorStatus.Fail)
                {
                    return EBehaviorStatus.Fail;
                }
                else if (status == EBehaviorStatus.Interrupt)
                {
                    return EBehaviorStatus.Interrupt;
                }
    
            }
            return EBehaviorStatus.Success;
        }
    }
    

    3.定义自己的结点
    这就要看自己的游戏需要满足的需求了
    这里就举几个例子:
    a.是否普攻不在cd
    b.血量在区间百分比
    c.血量高于百分比
    d.是否超过某个范围
    e.是否存在某个buff
    f.附近有怪物
    g.使用次数限制
    等等

    4.最后构造自己的行为树即可
    随便举个例子:

    SelectorNode selector = MakeNode<SelectorNode>();
    SequenceNode sq2 = MakeNode<SequenceNode>();
    CheckInDistance dis3 = MakeNode<CheckInDistance>();
    dis3.OnSetData(0, moveAwayParam);
    TriggerMoveType t = MakeNode<TriggerMoveType>();
    t.OnSetData(2);
    sq2.AddChild(dis3);
    sq2.AddChild(t);
    selector.AddChild(sq2);
    

    相关文章

      网友评论

        本文标题:简易行为树

        本文链接:https://www.haomeiwen.com/subject/motkyktx.html