上QQ阅读APP看书,第一时间看更新
How to do it...
This recipe will entail creating a new agent behavior:
- Create the AvoidAgent behavior, which is composed of a collision avoidance radius and the list of agents to avoid:
using UnityEngine; using System.Collections; using System.Collections.Generic; public class AvoidAgent : AgentBehaviour { public float collisionRadius = 0.4f; GameObject[] targets; }
- Implement the Start function in order to set the list of agents according to the tag we created earlier:
void Start () { targets = GameObject.FindGameObjectsWithTag("Agent"); }
- Define the GetSteering function:
public override Steering GetSteering() { // body }
- Add the following variables to the compute distances and velocities from agents that are nearby:
Steering steering = new Steering(); float shortestTime = Mathf.Infinity; GameObject firstTarget = null; float firstMinSeparation = 0.0f; float firstDistance = 0.0f; Vector3 firstRelativePos = Vector3.zero; Vector3 firstRelativeVel = Vector3.zero;
- Find the closest agent that is prone to collision with the current one:
foreach (GameObject t in targets) { Vector3 relativePos; Agent targetAgent = t.GetComponent<Agent>(); relativePos = t.transform.position - transform.position; Vector3 relativeVel = targetAgent.velocity - agent.velocity; float relativeSpeed = relativeVel.magnitude; float timeToCollision = Vector3.Dot(relativePos, relativeVel); timeToCollision /= relativeSpeed * relativeSpeed * -1; float distance = relativePos.magnitude; float minSeparation = distance - relativeSpeed * timeToCollision; if (minSeparation > 2 * collisionRadius) continue; if (timeToCollision > 0.0f && timeToCollision < shortestTime) { shortestTime = timeToCollision; firstTarget = t; firstMinSeparation = minSeparation; firstRelativePos = relativePos; firstRelativeVel = relativeVel; } }
- If there is one that is prone to collision, then move away:
if (firstTarget == null) return steering; if (firstMinSeparation <= 0.0f || firstDistance < 2 * collisionRadius) firstRelativePos = firstTarget.transform.position; else firstRelativePos += firstRelativeVel * shortestTime; firstRelativePos.Normalize(); steering.linear = -firstRelativePos * agent.maxAccel; return steering;