AeroplaneAiControl.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. using System;
  2. using UnityEngine;
  3. using Random = UnityEngine.Random;
  4. namespace UnityStandardAssets.Vehicles.Aeroplane
  5. {
  6. [RequireComponent(typeof (AeroplaneController))]
  7. public class AeroplaneAiControl : MonoBehaviour
  8. {
  9. // This script represents an AI 'pilot' capable of flying the plane towards a designated target.
  10. // It sends the equivalent of the inputs that a user would send to the Aeroplane controller.
  11. [SerializeField] private float m_RollSensitivity = .2f; // How sensitively the AI applies the roll controls
  12. [SerializeField] private float m_PitchSensitivity = .5f; // How sensitively the AI applies the pitch controls
  13. [SerializeField] private float m_LateralWanderDistance = 5; // The amount that the plane can wander by when heading for a target
  14. [SerializeField] private float m_LateralWanderSpeed = 0.11f; // The speed at which the plane will wander laterally
  15. [SerializeField] private float m_MaxClimbAngle = 45; // The maximum angle that the AI will attempt to make plane can climb at
  16. [SerializeField] private float m_MaxRollAngle = 45; // The maximum angle that the AI will attempt to u
  17. [SerializeField] private float m_SpeedEffect = 0.01f; // This increases the effect of the controls based on the plane's speed.
  18. [SerializeField] private float m_TakeoffHeight = 20; // the AI will fly straight and only pitch upwards until reaching this height
  19. [SerializeField] private Transform m_Target; // the target to fly towards
  20. private AeroplaneController m_AeroplaneController; // The aeroplane controller that is used to move the plane
  21. private float m_RandomPerlin; // Used for generating random point on perlin noise so that the plane will wander off path slightly
  22. private bool m_TakenOff; // Has the plane taken off yet
  23. // setup script properties
  24. private void Awake()
  25. {
  26. // get the reference to the aeroplane controller, so we can send move input to it and read its current state.
  27. m_AeroplaneController = GetComponent<AeroplaneController>();
  28. // pick a random perlin starting point for lateral wandering
  29. m_RandomPerlin = Random.Range(0f, 100f);
  30. }
  31. // reset the object to sensible values
  32. public void Reset()
  33. {
  34. m_TakenOff = false;
  35. }
  36. // fixed update is called in time with the physics system update
  37. private void FixedUpdate()
  38. {
  39. if (m_Target != null)
  40. {
  41. // make the plane wander from the path, useful for making the AI seem more human, less robotic.
  42. Vector3 targetPos = m_Target.position +
  43. transform.right*
  44. (Mathf.PerlinNoise(Time.time*m_LateralWanderSpeed, m_RandomPerlin)*2 - 1)*
  45. m_LateralWanderDistance;
  46. // adjust the yaw and pitch towards the target
  47. Vector3 localTarget = transform.InverseTransformPoint(targetPos);
  48. float targetAngleYaw = Mathf.Atan2(localTarget.x, localTarget.z);
  49. float targetAnglePitch = -Mathf.Atan2(localTarget.y, localTarget.z);
  50. // Set the target for the planes pitch, we check later that this has not passed the maximum threshold
  51. targetAnglePitch = Mathf.Clamp(targetAnglePitch, -m_MaxClimbAngle*Mathf.Deg2Rad,
  52. m_MaxClimbAngle*Mathf.Deg2Rad);
  53. // calculate the difference between current pitch and desired pitch
  54. float changePitch = targetAnglePitch - m_AeroplaneController.PitchAngle;
  55. // AI always applies gentle forward throttle
  56. const float throttleInput = 0.5f;
  57. // AI applies elevator control (pitch, rotation around x) to reach the target angle
  58. float pitchInput = changePitch*m_PitchSensitivity;
  59. // clamp the planes roll
  60. float desiredRoll = Mathf.Clamp(targetAngleYaw, -m_MaxRollAngle*Mathf.Deg2Rad, m_MaxRollAngle*Mathf.Deg2Rad);
  61. float yawInput = 0;
  62. float rollInput = 0;
  63. if (!m_TakenOff)
  64. {
  65. // If the planes altitude is above m_TakeoffHeight we class this as taken off
  66. if (m_AeroplaneController.Altitude > m_TakeoffHeight)
  67. {
  68. m_TakenOff = true;
  69. }
  70. }
  71. else
  72. {
  73. // now we have taken off to a safe height, we can use the rudder and ailerons to yaw and roll
  74. yawInput = targetAngleYaw;
  75. rollInput = -(m_AeroplaneController.RollAngle - desiredRoll)*m_RollSensitivity;
  76. }
  77. // adjust how fast the AI is changing the controls based on the speed. Faster speed = faster on the controls.
  78. float currentSpeedEffect = 1 + (m_AeroplaneController.ForwardSpeed*m_SpeedEffect);
  79. rollInput *= currentSpeedEffect;
  80. pitchInput *= currentSpeedEffect;
  81. yawInput *= currentSpeedEffect;
  82. // pass the current input to the plane (false = because AI never uses air brakes!)
  83. m_AeroplaneController.Move(rollInput, pitchInput, yawInput, throttleInput, false);
  84. }
  85. else
  86. {
  87. // no target set, send zeroed input to the planeW
  88. m_AeroplaneController.Move(0, 0, 0, 0, false);
  89. }
  90. }
  91. // allows other scripts to set the plane's target
  92. public void SetTarget(Transform target)
  93. {
  94. m_Target = target;
  95. }
  96. }
  97. }