1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- using UnityEngine;
- using System.Collections;
- public class F3DTurret : MonoBehaviour
- {
- public Transform hub; // Turret hub
- public Transform barrel; // Turret barrel
- RaycastHit hitInfo; // Raycast structure
- bool isFiring; // Is turret currently in firing state
-
- float hubAngle, barrelAngle; // Current hub and barrel angles
- // Project vector on plane
- Vector3 ProjectVectorOnPlane(Vector3 planeNormal, Vector3 vector)
- {
- return vector - (Vector3.Dot(vector, planeNormal) * planeNormal);
- }
- // Get signed vector angle
- float SignedVectorAngle(Vector3 referenceVector, Vector3 otherVector, Vector3 normal)
- {
- Vector3 perpVector;
- float angle;
-
- perpVector = Vector3.Cross(normal, referenceVector);
- angle = Vector3.Angle(referenceVector, otherVector);
- angle *= Mathf.Sign(Vector3.Dot(perpVector, otherVector));
- return angle;
- }
- // Turret tracking
- void Track()
- {
- if(hub != null && barrel != null)
- {
- // Construct a ray pointing from screen mouse position into world space
- Ray cameraRay = Camera.main.ScreenPointToRay(Input.mousePosition);
- // Raycast
- if (Physics.Raycast(cameraRay, out hitInfo, 500f))
- {
- // Calculate heading vector and rotation quaternion
- Vector3 headingVector = ProjectVectorOnPlane(hub.up, hitInfo.point - hub.position);
- Quaternion newHubRotation = Quaternion.LookRotation(headingVector);
- // Check current heading angle
- hubAngle = SignedVectorAngle(transform.forward, headingVector, Vector3.up);
-
- // Limit heading angle if required
- if (hubAngle <= -60)
- newHubRotation = Quaternion.LookRotation(Quaternion.Euler(0, -60, 0) * transform.forward);
- else if (hubAngle >= 60)
- newHubRotation = Quaternion.LookRotation(Quaternion.Euler(0, 60, 0) * transform.forward);
- // Apply heading rotation
- hub.rotation = Quaternion.Slerp(hub.rotation, newHubRotation, Time.deltaTime * 5f);
- // Calculate elevation vector and rotation quaternion
- Vector3 elevationVector = ProjectVectorOnPlane(hub.right, hitInfo.point - barrel.position);
- Quaternion newBarrelRotation = Quaternion.LookRotation(elevationVector);
- // Check current elevation angle
- barrelAngle = SignedVectorAngle(hub.forward, elevationVector, hub.right);
-
- // Limit elevation angle if required
- if (barrelAngle < -30)
- newBarrelRotation = Quaternion.LookRotation(Quaternion.AngleAxis(-30f, hub.right) * hub.forward);
- else if (barrelAngle > 15)
- newBarrelRotation = Quaternion.LookRotation(Quaternion.AngleAxis(15f, hub.right) * hub.forward);
- // Apply elevation rotation
- barrel.rotation = Quaternion.Slerp(barrel.rotation, newBarrelRotation, Time.deltaTime * 5f);
- }
- }
- }
- void Update()
- {
- // Track turret
- Track();
- // Fire turret
- if (!isFiring && Input.GetKeyDown(KeyCode.Mouse0))
- {
- isFiring = true;
- F3DFXController.instance.Fire();
- }
- // Stop firing
- if (isFiring && Input.GetKeyUp(KeyCode.Mouse0))
- {
- isFiring = false;
- F3DFXController.instance.Stop();
- }
- }
- }
|