F3DTurret.cs 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. using UnityEngine;
  2. using System.Collections;
  3. public class F3DTurret : MonoBehaviour
  4. {
  5. public Transform hub; // Turret hub
  6. public Transform barrel; // Turret barrel
  7. RaycastHit hitInfo; // Raycast structure
  8. bool isFiring; // Is turret currently in firing state
  9. float hubAngle, barrelAngle; // Current hub and barrel angles
  10. // Project vector on plane
  11. Vector3 ProjectVectorOnPlane(Vector3 planeNormal, Vector3 vector)
  12. {
  13. return vector - (Vector3.Dot(vector, planeNormal) * planeNormal);
  14. }
  15. // Get signed vector angle
  16. float SignedVectorAngle(Vector3 referenceVector, Vector3 otherVector, Vector3 normal)
  17. {
  18. Vector3 perpVector;
  19. float angle;
  20. perpVector = Vector3.Cross(normal, referenceVector);
  21. angle = Vector3.Angle(referenceVector, otherVector);
  22. angle *= Mathf.Sign(Vector3.Dot(perpVector, otherVector));
  23. return angle;
  24. }
  25. // Turret tracking
  26. void Track()
  27. {
  28. if(hub != null && barrel != null)
  29. {
  30. // Construct a ray pointing from screen mouse position into world space
  31. Ray cameraRay = Camera.main.ScreenPointToRay(Input.mousePosition);
  32. // Raycast
  33. if (Physics.Raycast(cameraRay, out hitInfo, 500f))
  34. {
  35. // Calculate heading vector and rotation quaternion
  36. Vector3 headingVector = ProjectVectorOnPlane(hub.up, hitInfo.point - hub.position);
  37. Quaternion newHubRotation = Quaternion.LookRotation(headingVector);
  38. // Check current heading angle
  39. hubAngle = SignedVectorAngle(transform.forward, headingVector, Vector3.up);
  40. // Limit heading angle if required
  41. if (hubAngle <= -60)
  42. newHubRotation = Quaternion.LookRotation(Quaternion.Euler(0, -60, 0) * transform.forward);
  43. else if (hubAngle >= 60)
  44. newHubRotation = Quaternion.LookRotation(Quaternion.Euler(0, 60, 0) * transform.forward);
  45. // Apply heading rotation
  46. hub.rotation = Quaternion.Slerp(hub.rotation, newHubRotation, Time.deltaTime * 5f);
  47. // Calculate elevation vector and rotation quaternion
  48. Vector3 elevationVector = ProjectVectorOnPlane(hub.right, hitInfo.point - barrel.position);
  49. Quaternion newBarrelRotation = Quaternion.LookRotation(elevationVector);
  50. // Check current elevation angle
  51. barrelAngle = SignedVectorAngle(hub.forward, elevationVector, hub.right);
  52. // Limit elevation angle if required
  53. if (barrelAngle < -30)
  54. newBarrelRotation = Quaternion.LookRotation(Quaternion.AngleAxis(-30f, hub.right) * hub.forward);
  55. else if (barrelAngle > 15)
  56. newBarrelRotation = Quaternion.LookRotation(Quaternion.AngleAxis(15f, hub.right) * hub.forward);
  57. // Apply elevation rotation
  58. barrel.rotation = Quaternion.Slerp(barrel.rotation, newBarrelRotation, Time.deltaTime * 5f);
  59. }
  60. }
  61. }
  62. void Update()
  63. {
  64. // Track turret
  65. Track();
  66. // Fire turret
  67. if (!isFiring && Input.GetKeyDown(KeyCode.Mouse0))
  68. {
  69. isFiring = true;
  70. F3DFXController.instance.Fire();
  71. }
  72. // Stop firing
  73. if (isFiring && Input.GetKeyUp(KeyCode.Mouse0))
  74. {
  75. isFiring = false;
  76. F3DFXController.instance.Stop();
  77. }
  78. }
  79. }