上海虹口龙之梦项目
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

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;
}
}
}