Files
2026-03-04 10:03:45 +08:00

231 lines
6.2 KiB
C#

using UnityEngine;
namespace UnityStandardAssets.Vehicles.Aeroplane
{
[RequireComponent(typeof(Rigidbody))]
public class AeroplaneController : MonoBehaviour
{
[SerializeField]
private float m_MaxEnginePower = 40f;
[SerializeField]
private float m_Lift = 0.002f;
[SerializeField]
private float m_ZeroLiftSpeed = 300f;
[SerializeField]
private float m_RollEffect = 1f;
[SerializeField]
private float m_PitchEffect = 1f;
[SerializeField]
private float m_YawEffect = 0.2f;
[SerializeField]
private float m_BankedTurnEffect = 0.5f;
[SerializeField]
private float m_AerodynamicEffect = 0.02f;
[SerializeField]
private float m_AutoTurnPitch = 0.5f;
[SerializeField]
private float m_AutoRollLevel = 0.2f;
[SerializeField]
private float m_AutoPitchLevel = 0.2f;
[SerializeField]
private float m_AirBrakesEffect = 3f;
[SerializeField]
private float m_ThrottleChangeSpeed = 0.3f;
[SerializeField]
private float m_DragIncreaseFactor = 0.001f;
private float m_OriginalDrag;
private float m_OriginalAngularDrag;
private float m_AeroFactor;
private bool m_Immobilized;
private float m_BankedTurnAmount;
private Rigidbody m_Rigidbody;
private WheelCollider[] m_WheelColliders;
public float Altitude { get; private set; }
public float Throttle { get; private set; }
public bool AirBrakes { get; private set; }
public float ForwardSpeed { get; private set; }
public float EnginePower { get; private set; }
public float MaxEnginePower => m_MaxEnginePower;
public float RollAngle { get; private set; }
public float PitchAngle { get; private set; }
public float RollInput { get; private set; }
public float PitchInput { get; private set; }
public float YawInput { get; private set; }
public float ThrottleInput { get; private set; }
private void Start()
{
m_Rigidbody = GetComponent<Rigidbody>();
m_OriginalDrag = m_Rigidbody.drag;
m_OriginalAngularDrag = m_Rigidbody.angularDrag;
for (int i = 0; i < base.transform.childCount; i++)
{
WheelCollider[] componentsInChildren = base.transform.GetChild(i).GetComponentsInChildren<WheelCollider>();
for (int j = 0; j < componentsInChildren.Length; j++)
{
componentsInChildren[j].motorTorque = 0.18f;
}
}
}
public void Move(float rollInput, float pitchInput, float yawInput, float throttleInput, bool airBrakes)
{
RollInput = rollInput;
PitchInput = pitchInput;
YawInput = yawInput;
ThrottleInput = throttleInput;
AirBrakes = airBrakes;
ClampInputs();
CalculateRollAndPitchAngles();
AutoLevel();
CalculateForwardSpeed();
ControlThrottle();
CalculateDrag();
CaluclateAerodynamicEffect();
CalculateLinearForces();
CalculateTorque();
CalculateAltitude();
}
private void ClampInputs()
{
RollInput = Mathf.Clamp(RollInput, -1f, 1f);
PitchInput = Mathf.Clamp(PitchInput, -1f, 1f);
YawInput = Mathf.Clamp(YawInput, -1f, 1f);
ThrottleInput = Mathf.Clamp(ThrottleInput, -1f, 1f);
}
private void CalculateRollAndPitchAngles()
{
Vector3 forward = base.transform.forward;
forward.y = 0f;
if (forward.sqrMagnitude > 0f)
{
forward.Normalize();
Vector3 vector = base.transform.InverseTransformDirection(forward);
PitchAngle = Mathf.Atan2(vector.y, vector.z);
Vector3 direction = Vector3.Cross(Vector3.up, forward);
Vector3 vector2 = base.transform.InverseTransformDirection(direction);
RollAngle = Mathf.Atan2(vector2.y, vector2.x);
}
}
private void AutoLevel()
{
m_BankedTurnAmount = Mathf.Sin(RollAngle);
if (RollInput == 0f)
{
RollInput = (0f - RollAngle) * m_AutoRollLevel;
}
if (PitchInput == 0f)
{
PitchInput = (0f - PitchAngle) * m_AutoPitchLevel;
PitchInput -= Mathf.Abs(m_BankedTurnAmount * m_BankedTurnAmount * m_AutoTurnPitch);
}
}
private void CalculateForwardSpeed()
{
ForwardSpeed = Mathf.Max(0f, base.transform.InverseTransformDirection(m_Rigidbody.velocity).z);
}
private void ControlThrottle()
{
if (m_Immobilized)
{
ThrottleInput = -0.5f;
}
Throttle = Mathf.Clamp01(Throttle + ThrottleInput * Time.deltaTime * m_ThrottleChangeSpeed);
EnginePower = Throttle * m_MaxEnginePower;
}
private void CalculateDrag()
{
float num = m_Rigidbody.velocity.magnitude * m_DragIncreaseFactor;
m_Rigidbody.drag = (AirBrakes ? ((m_OriginalDrag + num) * m_AirBrakesEffect) : (m_OriginalDrag + num));
m_Rigidbody.angularDrag = m_OriginalAngularDrag * ForwardSpeed;
}
private void CaluclateAerodynamicEffect()
{
if (m_Rigidbody.velocity.magnitude > 0f)
{
m_AeroFactor = Vector3.Dot(base.transform.forward, m_Rigidbody.velocity.normalized);
m_AeroFactor *= m_AeroFactor;
Vector3 velocity = Vector3.Lerp(m_Rigidbody.velocity, base.transform.forward * ForwardSpeed, m_AeroFactor * ForwardSpeed * m_AerodynamicEffect * Time.deltaTime);
m_Rigidbody.velocity = velocity;
m_Rigidbody.rotation = Quaternion.Slerp(m_Rigidbody.rotation, Quaternion.LookRotation(m_Rigidbody.velocity, base.transform.up), m_AerodynamicEffect * Time.deltaTime);
}
}
private void CalculateLinearForces()
{
Vector3 zero = Vector3.zero;
zero += EnginePower * base.transform.forward;
Vector3 normalized = Vector3.Cross(m_Rigidbody.velocity, base.transform.right).normalized;
float num = Mathf.InverseLerp(m_ZeroLiftSpeed, 0f, ForwardSpeed);
float num2 = ForwardSpeed * ForwardSpeed * m_Lift * num * m_AeroFactor;
zero += num2 * normalized;
m_Rigidbody.AddForce(zero);
}
private void CalculateTorque()
{
Vector3 zero = Vector3.zero;
zero += PitchInput * m_PitchEffect * base.transform.right;
zero += YawInput * m_YawEffect * base.transform.up;
zero += (0f - RollInput) * m_RollEffect * base.transform.forward;
zero += m_BankedTurnAmount * m_BankedTurnEffect * base.transform.up;
m_Rigidbody.AddTorque(zero * ForwardSpeed * m_AeroFactor);
}
private void CalculateAltitude()
{
Ray ray = new Ray(base.transform.position - Vector3.up * 10f, -Vector3.up);
Altitude = (Physics.Raycast(ray, out var hitInfo) ? (hitInfo.distance + 10f) : base.transform.position.y);
}
public void Immobilize()
{
m_Immobilized = true;
}
public void Reset()
{
m_Immobilized = false;
}
}
}