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.
177 lines
5.6 KiB
177 lines
5.6 KiB
11 months ago
|
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;
|
||
|
}
|
||
|
}
|
||
|
}
|