Unity 2018 Artificial Intelligence Cookbook(Second Edition)
上QQ阅读APP看书,第一时间看更新

How to do it...

This recipe will entail creating a new agent behavior:

  1. 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; 
} 
  1. 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"); 
} 
  1. Define the GetSteering function:
public override Steering GetSteering() 
{ 
    // body 
} 
  1. 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; 
  1. 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; 
    } 
} 
  1. 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;