【Unity/Tutorial】官方AircraftJetAI(四)喷射机首飞

说在前面

  • Unity版本:2017.4.37
  • 资源下载:这个资源是官方自带的资源,若没有,见这里
  • 说明:该项目为官方自带的项目,这里仅记录从零开始的搭建过程

系列目录

相关函数

移动喷射机

  • 在之前的章节中,我们创建的喷射机其实有一半是在我们创建的地面之下的,现在,在我们将喷射机组装好之后,我们可以轻易的将喷射机整体上移。
    在这里插入图片描述
  • 只需要调整AircraftJetAIPosition中的y即可
    在这里插入图片描述

添加刚体/BoxCollier组件

  • 刚体组件
    点击Inspector窗口中的Add Component搜索RigidBody并添加
    在这里插入图片描述

  • Box Collider组件
    点击Inspector窗口中的Add Component搜索Box Collider并添加;(若不添加该组件,将无法与创建的地面产生碰撞效果,导致飞机直接掉落)

    在这里插入图片描述
    通过调整Size将飞机刚好包裹住。
    在这里插入图片描述

控制器脚本

  • 创建文件夹Scripts
    在这里插入图片描述
    在这里插入图片描述
  • 进入该文件夹,右键创建新的c#脚本,命名为AeroplaneController
    在这里插入图片描述
    在这里插入图片描述
  • 为了描述喷射机的运动,首先需要了解一下俯仰 (pitch) - 偏摆 (yaw) - 翻滚 (roll)这三个角。
    在这里插入图片描述
  • 咱们知道,飞机通过引擎产生向前的推力,让飞机有一定的速度之后,由于飞机机翼的结构,就会产生升力。当升力大于重力时,飞机就能够飞起来了
    网上找的升力计算公式: L = 1 2 ρ v 2 C S L=\dfrac{1}{2}\rho v^2CS L=21ρv2CS
    其中 ρ \rho ρ为空气密度, v v v为飞机相对于空气的速度, C C C为升力系数, S S S为机翼投影面积。
    在我们的实验中,将上面这个公式简化: L = v 2 l L=v^2 l L=v2l
    其中 l l l为一个飞行时产生升力的系数(m_Lift);同时使用了一个叫m_ZeroLiftSpeed的参数,使用该参数的原因:The amount of lift drops off as the plane increases speed.(模拟飞行员在起飞后控制飞机的飞行速度,用以保持较低的飞行阻力,当然此时升力也会降低)
    在这里插入图片描述
    上图显示了飞机自身的坐标轴,其中蓝色为z轴,红色为x轴
  • 代码
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    namespace AircraftJetAI
    {
        public class AeroplaneController : MonoBehaviour
        {
            private float m_Lift = 0.002f;                      // 飞机飞行时产生的升力单位,简化
            private float m_ZeroLiftSpeed = 300;                // 飞机飞行速度达到这个值时,不再有升力
    
            private Rigidbody m_Rigidbody;                      // 刚体组件
    
            public float RollInput { get; private set; }        // 翻滚角输入
            public float PitchInput { get; private set; }       // 俯仰角输入
            public float YawInput { get; private set; }         // 偏摆角输入
            public float RollAngle { get; private set; }        // 翻滚角
            public float PitchAngle { get; private set; }       // 俯仰角
            public float ForwardSpeed { get; private set; }     // 飞机飞行的速度
    
            // 在脚本对象的第一帧时调用
            void Start()
            {
                m_Rigidbody = GetComponent<Rigidbody>();        // 获取刚体组件
            }
    
            // 移动函数
            public void Move(float rollInput, float pitchInput, float yawInput)                                  
            {
                RollInput = rollInput;
                PitchInput = pitchInput;
                YawInput = yawInput;
    
                // 暂时不用
                //ClampInputs();
                // 暂时不用
                //CalculateRollAndPitchAngles();
    
                CalculateForwardSpeed();
    
                CalculateLinearForces();
            }
    
            private void ClampInputs()
            {
                // 将角度输入限制在[-1,1]
                RollInput = Mathf.Clamp(RollInput, -1, 1);
                PitchInput = Mathf.Clamp(PitchInput, -1, 1);
                YawInput = Mathf.Clamp(YawInput, -1, 1);
            }
            private void CalculateRollAndPitchAngles()
            {
                // 计算当前的翻滚角以及俯仰角
                var flatForward = transform.forward;
                flatForward.y = 0;
                // 
                if (flatForward.sqrMagnitude > 0)
                {
                    flatForward.Normalize();
                    // 计算当前的俯仰角
                    var localFlatForward = transform.InverseTransformDirection(flatForward);
                    // 使用弧度制
                    PitchAngle = Mathf.Atan2(localFlatForward.y, localFlatForward.z);
                    // 计算当前的翻滚角
                    var flatRight = Vector3.Cross(Vector3.up, flatForward);
                    var localFlatRight = transform.InverseTransformDirection(flatRight);
                    RollAngle = Mathf.Atan2(localFlatRight.y, localFlatRight.x);
                }
            }
            private void CalculateForwardSpeed()
            {
                // 计算飞机自身的速度,沿自身z轴的方向
                var localVelocity = transform.InverseTransformDirection(m_Rigidbody.velocity);
                ForwardSpeed = Mathf.Max(0, localVelocity.z);
            }
            private void CalculateLinearForces()
            {
                //添加动力
                var forces = Vector3.zero;
                // 首先是模拟引擎产生的动力,假定固定为100,方向与飞机自身的z轴(机头指向的方向)相同
                forces += 100 * transform.forward;
                // 计算升力的方向,这里是用飞机的速度方向与飞机的x轴叉乘的方向
                var liftDirection = Vector3.Cross(m_Rigidbody.velocity, transform.right).normalized;
                // 然后是计算零升力因子,ForwardSpeed=m_ZeroLiftSpeed时,返回0;ForwardSpeed=0,返回1;
                var zeroLiftFactor = Mathf.InverseLerp(m_ZeroLiftSpeed, 0, ForwardSpeed);
                // 计算升力,简化了升力的计算公式
                var liftPower = ForwardSpeed * ForwardSpeed * m_Lift * zeroLiftFactor;
                // 添加升力
                forces += liftPower * liftDirection;
                // 应用力
                m_Rigidbody.AddForce(forces);
            }
        }
    }
    
  • 最后将该脚本添加到飞机对象上
    直接拖动到AircraftJetAI或者右边的Inspector窗口;或者点击Inspector窗口中的Add Component按钮并搜索
    在这里插入图片描述

用户控制脚本

  • 使用同样的方法创建脚本AeroplaneUserControl
  • 代码
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    namespace AircraftJetAI
    {
        public class AeroplaneUserControl : MonoBehaviour
        {
    
            // 用于访问飞机的控制器
            private AeroplaneController m_Aeroplane;
    
            // 在脚本对象(即飞机)被实例化的时候调用
            private void Awake()
            {
                // 获取脚本对象的AeroplaneController组件
                m_Aeroplane = GetComponent<AeroplaneController>();
            }
    
            // 真实时间下,固定时间间隔调用
            private void FixedUpdate()
            {
                // 获取用户的输入,A/D键控制左右,W/S键控制下上
                float roll = Input.GetAxis("Horizontal");
                float pitch = Input.GetAxis("Vertical");
                
                // 调用Move函数,此时控制还未激活(无法用wasd控制)
                m_Aeroplane.Move(roll, pitch, 0);
            }
    
        }
    }
    
  • 将该脚本添加到飞机对象上
    方法同上

飞行录像

在这里插入图片描述

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值