个体AI角色的操控行为de实现
2.4 Pursuit 追逐
using System.Collections; using System.Collections.Generic; using UnityEngine; /*追逐 * 类似于靠近行为,但目标是移动的,要实现的是可以预测目标未来的位置 * 使用简单的预测器,计算目标在未来时间T的目标位置,关键是确定预测间隔T */ public class SteeringForPursuit : Steering { public GameObject target; private Vector3 desiredVelocity; private Vehicle m_vehicle; private float maxSpeed; // Use this for initialization void Start () { m_vehicle = GetComponent<Vehicle>(); maxSpeed = m_vehicle.maxSpeed; } public override Vector3 Force() { Vector3 toTarget = target.transform.position - transform.position; //计算追逐者的前向与逃避者前向之间的夹角 float relativeDirection = Vector3.Dot(transform.forward, target.transform.forward); //如果夹角大于0,且追逐者基本面对着逃避者,那么直接向逃避者当前位置移动 if ((Vector3.Dot(toTarget, transform.forward) > 0) && (relativeDirection < -0.95f)) { desiredVelocity = (target.transform.position - transform.position).normalized * maxSpeed; //返回操控向量 return (desiredVelocity - m_vehicle.velocity); } //计算预测时间,正比于追逐者与逃避者的距离,反比于追逐者和逃避者的速度和 float lookaheadTime = toTarget.magnitude / (maxSpeed + target.GetComponent<Vehicle>().velocity.magnitude); //计算预期速度 desiredVelocity = (target.transform.position + target.GetComponent<Vehicle>().velocity * lookaheadTime - transform.position).normalized * maxSpeed; //返回操纵向量 return (desiredVelocity - m_vehicle.velocity); } // Update is called once per frame void Update () { } }
2.5 Evade 逃避
using System.Collections; using System.Collections.Generic; using UnityEngine; /*逃避 * 逃离预测位置 * */ public class SteeringForEvade : Steering { public GameObject target; private Vector3 desiredVelocity; private Vehicle m_vehicle; private float maxSpeed; // Use this for initialization void Start () { m_vehicle = GetComponent<Vehicle>(); maxSpeed = m_vehicle.maxSpeed; } public override Vector3 Force() { Vector3 toTarget = target.transform.position - transform.position; //向前预测的时间 float lookaheadTime = toTarget.magnitude / (maxSpeed + target.GetComponent<Vehicle>().velocity.magnitude); //计算预期速度 desiredVelocity = (transform.position - (target.transform.position + target.GetComponent<Vehicle>().velocity * lookaheadTime)) .normalized * maxSpeed; //返回操控向量 return (desiredVelocity - m_vehicle.velocity); } // Update is called once per frame void Update () { } }
2.6 Wander 随机徘徊
using System.Collections; using System.Collections.Generic; using UnityEngine; /*随机徘徊 * 类似于气缸曲轴传动 * 利用不同的连杆长度(Wander距离)、角色到圆心的距离(Wander半径)、每帧随机偏移大小,产生不同的随机运动 * 这个函数的效果与帧率相关 */ public class SteeringForWander : Steering { //徘徊半径,即Wander圈的半径 public float wanderRadius; //徘徊距离,即Wander圈凸出在AI角色前面的距离 public float wanderDistance; //每秒加到目标的随机位移的最大值 public float wanderJitter; public bool isPlanar; private Vector3 desiredVelocuty; private Vehicle m_vehicle; private float maxSpeed; private Vector3 circleTarget; private Vector3 wanderTarget; // Use this for initialization void Start () { m_vehicle = GetComponent<Vehicle>(); maxSpeed = m_vehicle.maxSpeed; isPlanar = m_vehicle.isPlanar; //选取圆圈上的一个点作为初始点 circleTarget = new Vector3(wanderRadius * 0.707f, 0, wanderRadius * 0.707f); } public override Vector3 Force() { //计算平均位移 Vector3 randomDisplacement = new Vector3((Random.value - 0.5f) * 2 * wanderJitter, (Random.value - 0.5f) * 2 * wanderJitter, (Random.value - 0.5f) * wanderJitter); if (isPlanar) randomDisplacement.y = 0; //将随机位移移加到初始点上,得到新的位置 circleTarget += randomDisplacement; //由于新位置很可能不在圆周上,因此需要投影到圆周上 circleTarget = wanderRadius * circleTarget.normalized; //之前计算出的值是相对AI角色和AI角色的前进方向的需要转换为世界坐标 wanderTarget = m_vehicle.velocity.normalized * wanderDistance + circleTarget + transform.position; //计算预期速度,返回操纵向量 desiredVelocuty = (wanderTarget - transform.position).normalized * maxSpeed; return (desiredVelocuty - m_vehicle.velocity); } // Update is called once per frame void Update () { } }