上一章地址: UnityStandardAsset工程、源码分析_4_赛车游戏[玩家控制]_摄像机控制

前几章我们已经将赛车游戏的绝大多数机制分析过了,而Unity还提供了不同的操控模式——AI控制。正如其名,是由AI来代替玩家进行控制,车辆自动绕场地行驶。AI控制的场景大体与玩家控制的场景相似,所以重复的部分不再赘述,我们着重分析AI相关的机制。
AI控制

AI控制场景的车附着的脚本,与玩家控制的车辆有所不同。第一章的截图中,车辆上附着了CarUserControl脚本,用于读入玩家输入并传给CarController,但这里的车辆上没有挂载CarUserControl,取而代之的是CarAIControl和WaypointProgressTracker。同时,在场景中也存在着如下对象:

Waypoints上挂载了WaypointCircuit:

此外,在第一章中,我们也观察到有一个名为WaypointTargetObject的物体,当时只是简略的提了一下这是用于AI相关的物体。而在这章中,它却扮演了一个非常重要的角色。
接下来我们根据上述提到的各个脚本、物体,来完整地分析AI驾驶的实现原理。我们先从CarAIControl入手:
namespace UnityStandardAssets.Vehicles.Car
{
[RequireComponent(typeof (CarController))]
public class CarAIControl : MonoBehaviour
{
// 三种行为模式
public enum BrakeCondition
{
// 一直加速,不减速
NeverBrake, // the car simply accelerates at full throttle all the time.
// 根据路径点之间的角度减速
TargetDirectionDifference, // the car will brake according to the upcoming change in direction of the target. Useful for route-based AI, slowing for corners.
// 在即将到达路近点的时候减速
TargetDistance, // the car will brake as it approaches its target, regardless of the target's direction. Useful if you want the car to
// head for a stationary target and come to rest when it arrives there.
}
// 这个脚本为车辆的控制提供了输入,就像玩家的输入一样
// 就这样,这是真的在“驾驶”车辆,没有使用什么特殊的物理或者动画效果
// This script provides input to the car controller in the same way that the user control script does.
// As such, it is really 'driving' the car, with no special physics or animation tricks to make the car behave properly.
// “闲逛”是用来让车辆变得更加像人类在操作,而不是机器在操作
// 他能在驶向目标的时候轻微地改变速度和方向
// "wandering" is used to give the cars a more human, less robotic feel. They can waver slightly
// in speed and direction while driving towards their target.
[SerializeField] [Range(0, 1)] private float m_CautiousSpeedFactor = 0.05f; // percentage of max speed to use when being maximally cautious
[SerializeField] [Range(0, 180)] private float m_CautiousMaxAngle = 50f; // angle of approaching corner to treat as warranting maximum caution
[SerializeField] private float m_CautiousMaxDistance = 100f; // distance at which distance-based cautiousness begins
[SerializeField] private float m_CautiousAngularVelocityFactor = 30f; // how cautious the AI should be when considering its own current angular velocity (i.e. easing off acceleration if spinning!)
[SerializeField] private float m_SteerSensitivity = 0.05f; // how sensitively the AI uses steering input to turn to the desired direction
[SerializeField] private float m_AccelSensitivity = 0.04f; // How sensitively the AI uses the accelerator to reach the current desired speed
[SerializeField] private float m_BrakeSensitivity = 1f; // How sensitively the AI uses the brake to reach the current desired speed
[SerializeField] private float m_LateralWanderDistance = 3f; // how far the car will wander laterally towards its target
[SerializeField] private float m_LateralWanderSpeed = 0.1f; // how fast the lateral wandering will fluctuate
[SerializeField] [Range(0, 1)] private float m_AccelWanderAmount = 0.1f; // how much the cars acceleration will wander
[SerializeField] private float m_AccelWanderSpeed = 0.1f; // how fast the cars acceleration wandering will fluctuate
[SerializeField] private BrakeCondition m_BrakeCondition = BrakeCondition.TargetDistance; // what should the AI consider when accelerating/braking?
[SerializeField] private bool m_Driving; // whether the AI is currently actively driving or stopped.
[SerializeField] private Transform m_Target; // 'target' the target object to aim for.
[SerializeField] private bool m_StopWhenTargetReached; // should we stop driving when we reach the target?
[SerializeField] private float m_ReachTargetThreshold = 2; // proximity to target to consider we 'reached' it, and stop driving.
private float m_RandomPerlin; // A random value for the car to base its wander on (so that AI cars don't all wander in the same pattern)
private CarController m_CarController; // Reference to actual car controller we are controlling
private float m_AvoidOtherCarTime; // time until which to avoid the car we recently collided with
private float m_AvoidOtherCarSlowdown; // how much to slow down due to colliding with another car, whilst avoiding
private float m_AvoidPathOffset; // direction (-1 or 1) in which to offset path to avoid other car, whilst avoiding
private Rigidbody m_Rigidbody;
private void Awake()
{
// 获得车辆的核心逻辑控件
// get the car controller reference
m_CarController = GetComponent<CarController>();
// 车辆闲逛的随机种子
// give the random perlin a random value
m_RandomPerlin = Random.value*100;
m_Rigidbody = GetComponent<Rigidbody>();
}
private void FixedUpdate()
{
if (m_Target == null || !m_Driving)
{
// 没有在驾驶或者没有目标时不应该移动,使用手刹来停下车辆
// Car should not be moving,
// use handbrake to stop
m_CarController.Move(0, 0, -1f, 1f);
}
else
{
// 正朝向,如果速度大于最大速度的10%,则为速度方向,否则为模型方向
Vector3 fwd = transform.forward;
if (m_Rigidbody.velocity.magnitude > m_CarController.MaxSpeed*0.1f)
{
fwd = m_Rigidbody.velocity;
}
float desiredSpeed = m_CarController.MaxSpeed;
// 现在是时候决定我们是否该减速了
// now it's time to decide if we should be slowing down...
switch (m_BrakeCondition)
{
// 根据路径点角度限制速度
case BrakeCondition.TargetDirectionDifference:
{
// the car will brake according to the upcoming change in direction of the target. Useful for route-based AI, slowing for corners.
// 先计算我们当前朝向与路径点的朝向之间的角度
// check out the angle of our target compared to the current direction of the car
float approachingCornerAngle = Vector3.Angle(m_Target.forward, fwd);
// 也考虑一下我们当前正在转向的角速度
// also consider the current amount we're turning, multiplied up and then compared in the same way as an upcoming corner angle
float spinningAngle <


1672

被折叠的 条评论
为什么被折叠?



