实现NPC的AI-行为树
行为树包括三种节点:
条件节点(Condition):表示一个条件,例如检查玩家是否在可攻击范围内。
行为节点(Action):表示一个具体的行为,例如攻击敌人。
复合节点(Composite):表示一种组合行为的方式,它可以包含其他节点,并定义它们之间的关系。常见的复合节点包括
- 序列节点(Sequence):序列节点按顺序执行其子节点,只有当一个子节点成功执行后才会执行下一个子节点。如果有任何一个子节点失败,整个序列节点将返回失败状态。
- 选择节点(Selector):选择节点按顺序执行其子节点,一旦遇到一个成功执行的子节点,选择节点将返回成功状态,不再执行后续子节点。只有当所有子节点都失败时,选择节点才会返回失败状态。
- 并行节点(Parallel):并行节点同时执行其所有子节点,不等待子节点的执行结果。
public abstract class BehaviorNode
{
public abstract BehaviorStatus Execute();
}
// 行为节点的执行状态
public enum BehaviorStatus
{
Success,
Failure,
Running
}
// 条件节点
public abstract class ConditionNode : BehaviorNode
{
public abstract bool Update();
public override BehaviorStatus Execute()
{
return Update() ? BehaviorStatus.Success : BehaviorStatus.Failure;
}
}
// 行为节点
public abstract class ActionNode : BehaviorNode
{
public abstract BehaviorStatus Update();
public override BehaviorStatus Execute()
{
return Update();
}
}
// 组合节点
public abstract class CompositeNode : BehaviorNode
{
protected List<BehaviorNode> childNodes = new List<BehaviorNode>();
public void AddChild(BehaviorNode node)
{
childNodes.Add(node);
}
public void RemoveChild(BehaviorNode node)
{
childNodes.Remove(node);
}
}
// 序列节点
public class SequenceNode : CompositeNode
{
public override BehaviorStatus Execute()
{
foreach (BehaviorNode node in childNodes)
{
BehaviorStatus status = node.Execute();
if (status != BehaviorStatus.Success)
return status;
}
return BehaviorStatus.Success;
}
}
// 选择节点
public class SelectorNode : CompositeNode
{
public override BehaviorStatus Execute()
{
foreach (BehaviorNode node in childNodes)
{
BehaviorStatus status = node.Execute();
if (status != BehaviorStatus.Failure)
return status;
}
return BehaviorStatus.Failure;
}
}
// 并行节点
public class ParallelNode : CompositeNode
{
public override BehaviorStatus Execute()
{
bool anyRunning = false;
foreach (BehaviorNode node in childNodes)
{
BehaviorStatus status = node.Execute();
if (status == BehaviorStatus.Failure)
return BehaviorStatus.Failure;
if (status == BehaviorStatus.Running)
anyRunning = true;
}
return anyRunning ? BehaviorStatus.Running : BehaviorStatus.Success;
}
}
public class EnemyAI
{
private BehaviorNode behaviorTree;
public EnemyAI()
{
// 创建行为树
behaviorTree = new SelectorNode();
SequenceNode attackSequence = new SequenceNode();
attackSequence.AddChild(new MoveToTargetNode());
attackSequence.AddChild(new AttackNode());
SequenceNode patrolSequence = new SequenceNode();
patrolSequence.AddChild(new PatrolNode());
((CompositeNode)behaviorTree).AddChild(attackSequence);
((CompositeNode)behaviorTree).AddChild(patrolSequence);
}
public void Update()
{
// 在游戏循环中执行行为树
behaviorTree.Execute();
}
}