说在前面
- Unity版本:2017.4.37
- 资源下载:这个资源是官方自带的资源,若没有,见这里
- 说明:该项目为官方自带的项目,这里仅记录从零开始的搭建过程
系列目录
- 【Unity/Tutorial】官方AircraftJetAI(一)导入资源与创建Camera
- 【Unity/Tutorial】官方AircraftJetAI(二)创建固定地形
- 【Unity/Tutorial】官方AircraftJetAI(三)创建喷射机
- 【Unity/Tutorial】官方AircraftJetAI(四)喷射机首飞
- 【Unity/Tutorial】官方AircraftJetAI(五)力矩与喷射机转向
力矩
- Wikipedia
- 如下图,力矩是在垂直方向上变化的箭头,力
F
F
F是作用在小球上变化的箭头,红色箭头是转动轴到着力点的距离矢量
r
r
r。力
F
F
F与距离矢量
r
r
r的叉积结果即力矩。
- 在Unity中,我们可以直接将力矩(而不是力)添加在刚体上。
如下图,若想要让飞机俯仰转动,那么就需要在x轴(红轴)上添加力矩
Banked Turn
译作“倾斜转弯”?
想象一下影视作品中的飞机转弯的情形- Wikipedia
如上图,绿色为升力,蓝色为重力,黄色为向心力。向心力影响了飞机的偏摆,即“转弯”。
代码
AeroplaneUserControl.cs
不变AeroplaneController.cs
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 float m_RollEffect = 1f; // 翻滚角输入的强度单位,这个值越大,在按键的时候越容易翻滚 private float m_PitchEffect = 1f; // 俯仰角输入的强度单位 private float m_YawEffect = 0.2f; // 偏摆角输入的强度单位 private float m_BankedTurnEffect = 0.5f; // 倾斜转弯的量,越大,越容易转弯 private Rigidbody m_Rigidbody; // 刚体组件 private float m_BankedTurnAmount; 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(); CalculateTorque(); } 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; // 首先是模拟引擎产生的动力,假定固定为40,方向与飞机自身的z轴(机头指向的方向)相同 forces += 40 * 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); } private void CalculateTorque() { // 计算力矩 var torque = Vector3.zero; // 依据俯仰角输入,计算飞机自身x轴方向上的力矩,此时力的方向应该是垂直于xoz平面的 torque += PitchInput * m_PitchEffect * transform.right; // 依据偏摆角输入,计算飞机自身y轴方向上的力矩 torque += YawInput * m_YawEffect * transform.up; // 依据翻滚角输入,计算飞机自身z轴方向上的力矩 torque += -RollInput * m_RollEffect * transform.forward; // 计算倾斜转弯时的力矩 m_BankedTurnAmount = Mathf.Sin(RollAngle); torque += m_BankedTurnAmount * m_BankedTurnEffect * transform.up; // 最终力矩是乘上了飞行速度大小的 m_Rigidbody.AddTorque(torque * ForwardSpeed); } } }
飞行录像
S
键向上,W
键向下