实现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();
    }
}
返回顶部