Files
2026-03-04 10:03:45 +08:00

172 lines
3.9 KiB
C#

using UnityEngine;
namespace Gaia
{
public class CameraController : MonoBehaviour
{
public GameObject target;
public float targetHeight = 5f;
public float distance = 12f;
public float offsetFromWall = 0.1f;
public float maxDistance = 20f;
public float minDistance = 0.6f;
public float xSpeed = 200f;
public float ySpeed = 200f;
public float yMinLimit = -80f;
public float yMaxLimit = 80f;
public float zoomRate = 40f;
public float rotationDampening = 0.5f;
public float zoomDampening = 5f;
public LayerMask collisionLayers = -1;
public bool lockToRearOfTarget;
public bool allowMouseInputX = true;
public bool allowMouseInputY = true;
private float xDeg;
private float yDeg;
private float currentDistance;
private float desiredDistance;
private float correctedDistance;
private bool rotateBehind;
private bool mouseSideButton;
private float pbuffer;
private void Start()
{
Vector3 eulerAngles = base.transform.eulerAngles;
xDeg = eulerAngles.x;
yDeg = eulerAngles.y;
currentDistance = distance;
desiredDistance = distance;
correctedDistance = distance;
if (lockToRearOfTarget)
{
rotateBehind = true;
}
if (target == null)
{
target = GameObject.FindGameObjectWithTag("Player");
}
}
private void LateUpdate()
{
if (target == null)
{
return;
}
if (pbuffer > 0f)
{
pbuffer -= Time.deltaTime;
}
if (pbuffer < 0f)
{
pbuffer = 0f;
}
if (mouseSideButton && Input.GetAxis("Vertical") != 0f)
{
mouseSideButton = false;
}
if (GUIUtility.hotControl == 0)
{
if (Input.GetMouseButton(0) || Input.GetMouseButton(1))
{
if (allowMouseInputX)
{
xDeg += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
}
else
{
RotateBehindTarget();
}
if (allowMouseInputY)
{
yDeg -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
}
if (!lockToRearOfTarget)
{
rotateBehind = false;
}
}
else if (Input.GetAxis("Vertical") != 0f || Input.GetAxis("Horizontal") != 0f || rotateBehind || mouseSideButton)
{
RotateBehindTarget();
}
}
yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);
Quaternion quaternion = Quaternion.Euler(yDeg, xDeg, 0f);
desiredDistance -= Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs(desiredDistance);
desiredDistance = Mathf.Clamp(desiredDistance, minDistance, maxDistance);
correctedDistance = desiredDistance;
Vector3 vector = new Vector3(0f, 0f - targetHeight, 0f);
Vector3 end = target.transform.position - (quaternion * Vector3.forward * desiredDistance + vector);
Vector3 vector2 = new Vector3(target.transform.position.x, target.transform.position.y + targetHeight, target.transform.position.z);
bool flag = false;
if (Physics.Linecast(vector2, end, out var hitInfo, collisionLayers))
{
correctedDistance = Vector3.Distance(vector2, hitInfo.point) - offsetFromWall;
flag = true;
}
currentDistance = ((!flag || correctedDistance > currentDistance) ? Mathf.Lerp(currentDistance, correctedDistance, Time.deltaTime * zoomDampening) : correctedDistance);
currentDistance = Mathf.Clamp(currentDistance, minDistance, maxDistance);
end = target.transform.position - (quaternion * Vector3.forward * currentDistance + vector);
base.transform.rotation = quaternion;
base.transform.position = end;
}
private void RotateBehindTarget()
{
float y = target.transform.eulerAngles.y;
float y2 = base.transform.eulerAngles.y;
xDeg = Mathf.LerpAngle(y2, y, rotationDampening * Time.deltaTime);
if (y == y2)
{
if (!lockToRearOfTarget)
{
rotateBehind = false;
}
}
else
{
rotateBehind = true;
}
}
private float ClampAngle(float angle, float min, float max)
{
if (angle < -360f)
{
angle += 360f;
}
if (angle > 360f)
{
angle -= 360f;
}
return Mathf.Clamp(angle, min, max);
}
}
}