UnityStandardAsset工程、源码分析_5_赛车游戏[AI控制]_AI机制

上一章地址: UnityStandardAsset工程、源码分析_4_赛车游戏[玩家控制]_摄像机控制
在这里插入图片描述
前几章我们已经将赛车游戏的绝大多数机制分析过了,而Unity还提供了不同的操控模式——AI控制。正如其名,是由AI来代替玩家进行控制,车辆自动绕场地行驶。AI控制的场景大体与玩家控制的场景相似,所以重复的部分不再赘述,我们着重分析AI相关的机制。

AI控制

在这里插入图片描述
AI控制场景的车附着的脚本,与玩家控制的车辆有所不同。第一章的截图中,车辆上附着了CarUserControl脚本,用于读入玩家输入并传给CarController,但这里的车辆上没有挂载CarUserControl,取而代之的是CarAIControlWaypointProgressTracker。同时,在场景中也存在着如下对象:
在这里插入图片描述
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 <
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值