1.靠近
创建一个类SteeringForSeek继承Steering,将目标物体拖入Target,我们的AI就会自动向Target靠近。
重写其中的Force方法 在Vehicle中会遍历所有的Steering的子类,我们实现的靠近类重写的Force就会被加入Vehicle的力中来实现物体的移动
代码语言:javascript复制public class SteeringForSeek : Steering {
public GameObject target;
Vector3 desiredVelocity;
//获得被操控的AI角色以便查询最大速度的等信息
Vehicle m_vehicle;
float maxSpeed;
bool isPlanar;
// Use this for initialization
void Start () {
m_vehicle = GetComponent<Vehicle>();
maxSpeed = m_vehicle.maxSpeed;
isPlanar = m_vehicle.isPlanar;
}
public override Vector3 Force()
{
//预期速度
desiredVelocity = (target.transform.position - transform.position).normalized
* maxSpeed;
//只在平面上运动
if (isPlanar)
{
desiredVelocity.y = 0;
}
return (desiredVelocity - m_vehicle.velocity);
}
}
2.离开
相比于上面的Seek,Flee的desriedVelocity是反方向的。 将追逐此AI的物体拖入Target,在target进入AI的危险感知范围时,AI将进行逃跑
代码语言:javascript复制public class SteeringForFlee : Steering {
public GameObject target;
//AI意识到危险的范围
public float fearDistance = 20;
Vector3 desiredVelocity;
Vehicle m_vehicle;
float maxSpeed;
void Start () {
m_vehicle = GetComponent<Vehicle>();
maxSpeed = m_vehicle.maxSpeed;
}
public override Vector3 Force()
{
Vector3 tempPos = new Vector3(transform.position.x,
0, transform.position.z);
Vector3 tempTargetPos = new Vector3(target.transform.position.x,
0, target.transform.position.z);
if (Vector3.Distance(tempPos, tempTargetPos) > fearDistance)
{
return new Vector3(0, 0, 0);
}
desiredVelocity = (transform.position - target.transform.position)
.normalized * maxSpeed;
return desiredVelocity - m_vehicle.velocity;
}
}
Capsule追随 Sphere逃离
3.抵达
我们希望AI在到达目标的时候减小速度,避免冲过目标,AI进入停止半径后,将逐渐减小预期速度,直到降为0. 如果距离大于减速半径,将预期速度设为最大速度,如果AI进入减速半径,AI将与其速度设置为目标距离减去当前速度,
代码语言:javascript复制public class SteeringForArrive : Steering {
public bool isPlanar = true;
public float arrivalDistance = 0.3f;
public float characterRadius = 1.2f;
//与目标小于此距离时开始减速
public float slowDownDistance;
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;
isPlanar = m_vehicle.isPlanar;
}
public override Vector3 Force()
{
Vector3 toTarget = target.transform.position - transform.position;
Vector3 desiredVelocity;
Vector3 returnForce;
if (isPlanar)
{
toTarget.y = 0;
}
float distance = toTarget.magnitude;
if(distance > slowDownDistance)
{
desiredVelocity = toTarget.normalized * maxSpeed;
returnForce = desiredVelocity - m_vehicle.velocity;
}
else
{
desiredVelocity = toTarget - m_vehicle.velocity;
//返回预期速度和当前速度的差值
returnForce = desiredVelocity - m_vehicle.velocity;
}
return returnForce;
}
}
Arrive.gif
4.追逐
追逐与Arrive很相似,不过目标不再是静止的,而是在移动的,最简单的方法是,让AI直接向目标位置靠近,但我们要让AI预测目标未来的位置,让AI朝着目标未来的位置进行移动,通过一个简单地预测器,来让目标向目标未来位置进行移动.
代码语言:javascript复制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(target.transform.forward, transform.forward);
if (Vector3.Dot(toTarget,transform.forward)>0 &&
(relativeDirection > 0.95f))
{
desiredVelocity = (target.transform.position - transform.position)
.normalized * maxSpeed;
return desiredVelocity - m_vehicle.velocity;
}
//预测时间的长短:正比于到目标位置的距离,反比与目标和AI的速度和
float lookaheadTime = toTarget.magnitude / (target.GetComponent<Vehicle>().velocity.magnitude
maxSpeed);
//预期速度
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 () {
}
}
普通的接近:
SimpleArrive.gif
预测未来位置后:
Pursuit.gif
延长预测时间:
Pursuit2.gif