You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中如何在行为树内调用并执行Wander Steering Behaviour?

解决方案:在行为树中整合漫游转向行为

问题的核心是:仅添加Wander组件无法触发行为,因为转向行为需要持续调用其GetSteering方法,且行为树需要管理该行为的生命周期(启动、运行、终止)。以下是具体实现步骤:

1. 改造Agent类,管理转向行为的启用/禁用

首先在Agent类中添加方法,用于启动、停止漫游行为,并确保默认禁用漫游组件:

public class Agent : MonoBehaviour
{
    public SteeringBehaviours steeringBehaviours;
    private Wander wanderBehaviour;

    private void Awake()
    {
        // 初始化时获取或添加Wander组件,默认禁用
        wanderBehaviour = GetComponent<Wander>();
        if (wanderBehaviour == null)
        {
            wanderBehaviour = gameObject.AddComponent<Wander>();
        }
        wanderBehaviour.enabled = false;
    }

    // 启动漫游:禁用其他转向行为,启用漫游
    public void StartWander()
    {
        foreach (Steering steering in GetComponents<Steering>())
        {
            if (steering != wanderBehaviour)
                steering.enabled = false;
        }
        wanderBehaviour.enabled = true;
    }

    // 停止漫游
    public void StopWander()
    {
        wanderBehaviour.enabled = false;
    }

    // 保留原有移动到目标的方法
    public void AgentMoveTo(Vector3 target)
    {
        // 你的原有移动逻辑
    }
}

2. 创建行为树漫游节点AgentWander

编写专门的行为树节点,负责控制漫游行为的启动、持续运行,以及在发现敌人时终止:

public class AgentWander : BTNode
{
    private AgentBB aBB;
    private Agent agentRef;
    private bool isWanderingStarted = false;

    public AgentWander(Blackboard bb, Agent agent) : base(bb)
    {
        aBB = (AgentBB)bb;
        agentRef = agent;
    }

    public override BTStatus Execute()
    {
        // 检查是否发现敌人:若发现则终止漫游,切换到战斗逻辑
        if (aBB.enemyLocation != Vector3.zero) // 假设enemyLocation为Vector3.zero表示未发现敌人
        {
            agentRef.StopWander();
            isWanderingStarted = false;
            return BTStatus.SUCCESS;
        }

        // 第一次执行时启动漫游
        if (!isWanderingStarted)
        {
            isWanderingStarted = true;
            agentRef.StartWander();
            Debug.Log("Started wandering");
        }

        // 持续漫游,直到发现敌人
        return BTStatus.RUNNING;
    }
}

3. 确保SteeringBehaviours持续调用转向逻辑

修改SteeringBehaviours类,在每帧获取启用的转向行为的力,并应用到Agent的刚体上:

public class SteeringBehaviours : MonoBehaviour
{
    public float maxAcceleration;
    public float maxSpeed;
    private Rigidbody rb;

    private void Awake()
    {
        rb = GetComponent<Rigidbody>();
    }

    private void FixedUpdate()
    {
        SteeringData totalSteering = new SteeringData();

        // 累加所有启用的转向行为的力
        foreach (Steering behaviour in GetComponents<Steering>())
        {
            if (behaviour.enabled)
            {
                totalSteering += behaviour.GetSteering(this);
            }
        }

        // 应用转向力并限制速度
        rb.AddForce(totalSteering.linear);
        if (rb.velocity.magnitude > maxSpeed)
        {
            rb.velocity = rb.velocity.normalized * maxSpeed;
        }
    }
}

4. 补充SteeringData的累加支持

确保SteeringData结构体支持力的累加操作:

public struct SteeringData
{
    public Vector3 linear;
    public float angular;

    public static SteeringData operator +(SteeringData a, SteeringData b)
    {
        return new SteeringData
        {
            linear = a.linear + b.linear,
            angular = a.angular + b.angular
        };
    }
}

5. 调整行为树结构

在原有行为树中添加选择节点:

  • 优先判断Blackboard中是否存在敌人位置(enemyLocation非零)
  • 若未发现敌人:执行AgentWander节点
  • 若发现敌人:执行AgentMoveToEnemy节点

内容的提问来源于stack exchange,提问作者Fernando Silva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 07:12:40