简易行为树

行为树(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);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值