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
相关产品推荐
相关产品推荐

