行为树(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);
网友评论