You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
176 lines
5.6 KiB
176 lines
5.6 KiB
using UnityEngine; |
|
|
|
public class ThirdPersonCamera : MonoBehaviour |
|
{ |
|
public Transform target; |
|
public FiremanControl firemanControl; |
|
[SerializeField] LayerMask collisionLayers = new LayerMask(); |
|
private readonly bool AllowRotation = true; |
|
[SerializeField] private Vector2 targetOffset = new Vector2(); |
|
[HideInInspector] public bool stayBehindTarget = false; |
|
|
|
private Transform objectsToRotate; |
|
|
|
public Vector2 originRotation = new Vector2(); |
|
private bool returnToOrigin = true; |
|
private float returnSmoothing = 3; |
|
|
|
|
|
public float distance = 5; |
|
public float minDistance = 0; |
|
public float maxDistance = 10; |
|
|
|
private Vector2 sensitivity = new Vector2(3, 3); |
|
|
|
private float zoomSpeed = 1; |
|
private float zoomSmoothing = 16; |
|
private float zoomAltDelay = 0.5f; |
|
|
|
private float minAngle = -90; |
|
private float maxAngle = 90; |
|
|
|
private float _zoom_in_timer = 0; |
|
private float _zoom_out_timer = 0; |
|
|
|
[HideInInspector] public float _wanted_distance; |
|
private Quaternion _rotation; |
|
private Vector2 _input_rotation; |
|
|
|
private Transform _t; |
|
|
|
void Start() |
|
{ |
|
_t = transform; |
|
_wanted_distance = distance; |
|
_input_rotation = originRotation; |
|
|
|
// If no target set, warn the user |
|
if (!target) |
|
{ |
|
Debug.LogWarning("ThirdPersonCamera: No initial target set"); |
|
} |
|
|
|
} |
|
|
|
void Update() |
|
{ |
|
|
|
if (target) |
|
{ |
|
if (firemanControl.driving) |
|
{ |
|
objectsToRotate = firemanControl.carCamPoint.transform; |
|
stayBehindTarget = true; |
|
} |
|
|
|
else |
|
{ |
|
objectsToRotate = firemanControl.transform; |
|
stayBehindTarget = false; |
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
// Camera movement should be done in LateUpdate(), |
|
// but it is slightly choppy for some reason so changed to FixedUpdate() |
|
// seems to be working fine |
|
void FixedUpdate() |
|
{ |
|
if (target) |
|
{ |
|
// Zoom control |
|
if (Input.GetAxis("Mouse ScrollWheel") < 0 || _zoom_out_timer > zoomAltDelay) |
|
{ |
|
_wanted_distance += zoomSpeed; |
|
} |
|
else if (Input.GetAxis("Mouse ScrollWheel") > 0 || _zoom_in_timer > zoomAltDelay) |
|
{ |
|
_wanted_distance -= zoomSpeed; |
|
} |
|
|
|
// Prevent wanted distance from going below or above min and max distance |
|
_wanted_distance = Mathf.Clamp(_wanted_distance, minDistance, maxDistance); |
|
|
|
// If user clicks, change position based on drag direction and sensitivity |
|
// Stop at 90 degrees above / below object |
|
|
|
if (AllowRotation && (Input.GetMouseButton(0) || Input.GetMouseButton(1))) |
|
{ |
|
_input_rotation.x += Input.GetAxis("Mouse X") * sensitivity.x; |
|
|
|
ClampRotation(); |
|
|
|
_input_rotation.y -= Input.GetAxis("Mouse Y") * sensitivity.y; |
|
|
|
_input_rotation.y = Mathf.Clamp(_input_rotation.y, minAngle, maxAngle); |
|
|
|
_rotation = Quaternion.Euler(_input_rotation.y, _input_rotation.x, 0); |
|
|
|
// If user is right clicking, set the default position to the current position |
|
if (Input.GetMouseButton(1)) |
|
{ |
|
objectsToRotate.rotation = Quaternion.Euler(0, _input_rotation.x, 0); |
|
originRotation = _input_rotation; |
|
ClampRotation(); |
|
} |
|
} |
|
else |
|
{ |
|
if (stayBehindTarget) |
|
{ |
|
originRotation.x = target.eulerAngles.y; |
|
ClampRotation(); |
|
} |
|
// If Return To Origin, move camera back to the default position |
|
if (returnToOrigin) |
|
{ |
|
_input_rotation = Vector3.Lerp(_input_rotation, originRotation, returnSmoothing * Time.deltaTime); |
|
} |
|
|
|
_rotation = Quaternion.Euler(_input_rotation.y, _input_rotation.x, 0); |
|
} |
|
|
|
// Lerp from current distance to wanted distance |
|
distance = Mathf.Clamp(Mathf.Lerp(distance, _wanted_distance, Time.deltaTime * zoomSmoothing), minDistance, maxDistance); |
|
|
|
// Set wanted position based off rotation and distance |
|
Vector3 wanted_position = _rotation * new Vector3(targetOffset.x, 0, -_wanted_distance - 0.2f) + target.position + new Vector3(0, targetOffset.y, 0); |
|
Vector3 current_position = _rotation * new Vector3(targetOffset.x, 0, 0) + target.position + new Vector3(0, targetOffset.y, 0); |
|
|
|
RaycastHit hit; |
|
|
|
if (Physics.Linecast(current_position, wanted_position, out hit, collisionLayers)) |
|
{ |
|
distance = Vector3.Distance(current_position, hit.point) - 0.2f; |
|
} |
|
|
|
|
|
// Set the position and rotation of the camera |
|
_t.position = _rotation * new Vector3(targetOffset.x, 0.0f, -distance) + target.position + new Vector3(0, targetOffset.y, 0); |
|
_t.rotation = _rotation; |
|
} |
|
} |
|
|
|
private void ClampRotation() |
|
{ |
|
if (originRotation.x < -180) |
|
{ |
|
originRotation.x += 360; |
|
} |
|
else if (originRotation.x > 180) |
|
{ |
|
originRotation.x -= 360; |
|
} |
|
|
|
if (_input_rotation.x - originRotation.x < -180) |
|
{ |
|
_input_rotation.x += 360; |
|
} |
|
else if (_input_rotation.x - originRotation.x > 180) |
|
{ |
|
_input_rotation.x -= 360; |
|
} |
|
} |
|
}
|
|
|