标签:virt fail sele node running success rri var enum
接触到的第一个游戏AI制作方法就是行为树,我们游戏要做机器人,所以学以致用,实现了一个简单版的行为树.
行为树主要包含两类节点,一类是叶子节点:主要作用是实现功能;一类是复合节点:主要作用是控制.
行为树就是通过对不同的叶子节点进行组合后来达到AI控制效果的,每个叶子节点都会向其父节点报告执行状态,父节点再根据自己的逻辑改变自身状态,如此向上递归则可知整个行为树的状态.
- 动作节点:执行到此节点时,会执行一个动作,执行后返回执行成功.
- 条件节点:执行到此节点时,会进行条件判断,若条件判断成功返回执行成功否则返回执行失败.
- 等待节点:一般实现为执行到此节点时,会等待一段时间,若未超出等待时间则返回执行中,若超出等到时间则返回执行成功
- 序列节点:执行到此节点时,会依次执行其子节点,若有子节点返回执行中,则其状态也为执行中,并等待该子节点执行完毕,若有子节点执行失败,其状态也为执行失败,若所有子节点执行成功,则其状态也为执行成功(相当于&).)
- 选择节点:执行到此节点时,会依次执行其子节点,若有子节点返回执行中,则其状态也为执行中,并等待该自己点执行完毕.若有子节点执行成功,其状态也为执行成功,若所有子节点执行失败,则其状态为执行失败(相当于|).
- 并行节点:
以上就是行为树的几种基本节点
public enum NodeType
{
Action
, Condition
, Wait
, Sequence
, Select
}
public enum NodeState
{
Ready
, Running
, Success
, Failed
}
public class BehaviorTree
{
private readonly BtNode _rootNode;
private BtNode _runingNode;
public NodeState State { get; private set; }
public BehaviorTree(BtNode root)
{
_rootNode = root;
State = NodeState.Ready;
}
public NodeState Update()
{
State = _rootNode.OnVisit();
return State;
}
public void Reset()
{
_rootNode.Reset();
}
}
#region 节点定义
public abstract class BtNode
{
public NodeType Type { get; private set; }
public NodeState State { get; protected set; }
protected BtNode(NodeType nodeType)
{
State = NodeState.Ready;
Type = nodeType;
}
public abstract NodeState OnVisit();
public virtual void Reset()
{
State = NodeState.Ready;
}
}
public abstract class BtCompostieNode : BtNode
{
protected List<BtNode> ChildNodes;
protected BtCompostieNode(List<BtNode> nodes, NodeType nodeType) : base(nodeType)
{
ChildNodes = nodes ?? new List<BtNode>();
}
public virtual BtCompostieNode AddChild(BtNode node)
{
ChildNodes.Add(node);
return this;
}
}
#region 叶子节点
// 动作节点
public class ActionNode : BtNode
{
private readonly Action _action;
public ActionNode(Action action) : base(NodeType.Action)
{
_action = action;
}
public override NodeState OnVisit()
{
_action?.Invoke();
return NodeState.Success;
}
}
// 条件节点
public class ConditionNode : BtNode
{
private readonly Func<bool> _checkFunc;
public ConditionNode(Func<bool> checkFunc) : base(NodeType.Condition)
{
_checkFunc = checkFunc;
}
public override NodeState OnVisit()
{
if (_checkFunc == null)
return NodeState.Success;
return _checkFunc.Invoke() ? NodeState.Success : NodeState.Failed;
}
}
// 等待节点
public class WaitNode : BtNode
{
private readonly int _waitSec;
private long _startSec;
public WaitNode(int waitSec) : base(NodeType.Wait)
{
_waitSec = waitSec;
}
public override NodeState OnVisit()
{
if (_startSec == 0)
{
_startSec = DateTime.Now.Ticks / TimeSpan.TicksPerSecond;
State = NodeState.Running;
Console.WriteLine(DateTime.Now.Ticks / TimeSpan.TicksPerSecond);
}
// 还没有到时间返回running
if (DateTime.Now < new DateTime((_waitSec + _startSec) * TimeSpan.TicksPerSecond))
return State;
Console.WriteLine(DateTime.Now.Ticks / TimeSpan.TicksPerSecond);
State = NodeState.Success;
return State;
}
public override void Reset()
{
base.Reset();
_startSec = 0;
}
}
#endregion
#region 复合节点
public class SequenceNode : BtCompostieNode
{
public SequenceNode(List<BtNode> nodes = null) : base(nodes, NodeType.Sequence)
{
}
public override NodeState OnVisit()
{
foreach (var node in ChildNodes)
{
var result = node.OnVisit();
if (result != NodeState.Success)
return result;
}
return NodeState.Success;
}
}
public class SelectNode : BtCompostieNode
{
public SelectNode(List<BtNode> nodes = null) : base(nodes, NodeType.Select)
{
}
public override NodeState OnVisit()
{
foreach (var node in ChildNodes)
{
var result = node.OnVisit();
if (result != NodeState.Failed)
return result;
}
return NodeState.Failed;
}
}
标签:virt fail sele node running success rri var enum
原文地址:https://www.cnblogs.com/Fallever/p/9710821.html