增加Steering的派生类
----SteeringForWander类 徘徊行为类
解读:
①初始化过程,通过半径确定圆周上的一个点。(案例中通过确定一个X=Y的点(x,y)).
通过圆心公式: 圆心为(0,0)半径为r
又因为X=Y
我们可以算出关系式
所以初始化点的坐标为 Vector3(,0,)
A) 案例生成随机点的公式,通过随机值以及设定的抖动值,来生成一个随机位移的点。通过把初始化点的位置与随机点的位置相加,获取新的点。
B)通过将新的点进行向量归一化运算,获取新的点的方向向量,然后乘上徘徊范围的半径,可以将该点投影回徘徊范围的圆周上。 circleTarget
C)通过当前物体的速度矢量的归一化*徘徊距离(wanderDistance),获取物体将移动的距离,然后与B)中新投影点相加,获得目标(新投影点)在物体移动后的相对位置。由于目标的位置向量是相对物体(三角形)的,所以需要再与物体的位置相加而得到目标的实际位置(在世界坐标上的位置)。即实际要徘徊到的目标位置 wanderTarget
0)通过实际徘徊目标位置与物体当前位置的差值的归一化,求出实际运动方向,再乘上最大速度,求得物体运动的预期速度。通过预期速度与物体原速度的差值,获得实际操控力向量。
案例代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SteeringForWander : Steering {
//徘徊半径
public float wanderRadius;
//徘徊前距离
public float wanderDistance;
//每秒加到目标的随机位移最大值
public float wanderJitter;
public bool isPlanar;
private Vector3 desiredVelocity;
private Vehicle m_vehicle;
private float maxSpeed;
private Vector3 circleTarget;
private Vector3 wanderTarget;
private 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) * 2 * wanderJitter);
if (isPlanar)
randomDisplacement.y = 0;
//将随机位移加到初始点上,得到新位置
circleTarget += randomDisplacement;
//由于新位置可能不在圆周上,因此需要投影到圆周上
circleTarget = wanderRadius * circleTarget.normalized;
//之前计算出的值是相对于AI角色合AI角色的向前方向的,需要转换为世界坐标
wanderTarget = m_vehicle.velocity.normalized * wanderDistance + circleTarget + transform.position;
//计算预期速度 返回操控力向量
desiredVelocity = (wanderTarget - transform.position).normalized * maxSpeed;
return (desiredVelocity - m_vehicle.velocity);
}
}
参考书籍:《unity3d人工智能编程精粹》 王洪源等著 《C++游戏人工智能编程案例精粹》[美]Mat Buckland 图解来源P88-P89