NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Gameplay/Camera/CameraController.cs

7 lines
11 KiB
C#
Raw Normal View History

2024-10-18 18:57:44 +08:00
using System; using DG.Tweening; using Framework; using Gameplay.Performance; using UnityEngine; using Sirenix.OdinInspector; using Gameplay.Guide; [ExecuteAlways] public class CameraController : MonoBehaviour { private const float CameraStartY = 25; private const float CameraStartSize = 12; private const float CameraStartFOV = 30; private const float NearClipPlane = 0.03f; private const float FarClipPlane = 150; private readonly Vector3 cameraStartRotationO = new Vector3(37.5f, -10f, 0f); private readonly Vector3 cameraStartRotationP = new Vector3(45, -10, 0); //之前的缩放是6次滚轮从最小放到最大故每一次缩放的值为1/6f private const float ZoomStep = 1 / 12f; public float leftMargin = 1.5f; public float rightMargin = 1.5f; public float topMargin = 0.9f; public float bottomMargin = 0.9f; public float moveSpeedX = 0.19f; public float moveSpeedY = 0.3f; public float unitPerPixel = 0.01f; [ShowIf("isFightCamera")] public float CameraMinSize = 6; [ShowIf("isFightCamera")] public float CameraMaxSize = 12; [HideIf("isFightCamera")] public BoxCollider boxBounds; [HideIf("isFightCamera")] public float CameraMinFOV = 15; [HideIf("isFightCamera")] public float CameraMaxFOV = 30; [LabelText("是否战斗相机")] public bool isFightCamera = true; private Camera mainCamera; private bool isIgnoreZoomLimit; public Bounds CameraBounds { get; set; } private bool isOrthographic => mainCamera.orthographic; //Camera拖动控制 public static bool FingerMoveEnable = true; //size,将透视和正交相机的fov和orthographic size整合为统一数值 private float Size { get { if (isOrthographic) return mainCamera.orthographicSize; else { var fov = mainCamera.fieldOfView; //这里乘(CameraMaxSize - CameraMinSize)/(CameraMaxFOV - CameraMinFOV)是将fov的区间变得和orthographic size区间一致 return fov * (CameraMaxSize - CameraMinSize) / (CameraMaxFOV - CameraMinFOV); } } } //缩放百分比0表示放到最小1表示放到最大 private float ZoomScale { get { if (isOrthographic) return (CameraMaxSize - mainCamera.orthographicSize) / (CameraMaxSize - CameraMinSize); else return (CameraMaxFOV - mainCamera.fieldOfView) / (CameraMaxFOV - CameraMinFOV); } set { var t = Mathf.Clamp(value, 0, 1); if (Math.Abs(ZoomScale - t) < float.Epsilon) return; if (isOrthographic) mainCamera.orthographicSize = Mathf.Lerp(CameraMaxSize, CameraMinSize, t); else mainCamera.fieldOfView = Mathf.Lerp(CameraMaxFOV, CameraMinFOV, t); } } private void Awake() { mainCamera = GetComponent<Camera>(); if (isFightCamera) { var useOrthographic = PerformanceManager.instance != null && PerformanceManager.instance.data.fightUseOrthographic; var rotEuler = useOrthographic ? cameraStartRotationO : cameraStartRotationP; if (useOrthographic) { // TODO: 这里的值是固定的,需要根据实际情况调整 //bottomMargin = 0.9f; mainCamera.orthographic = true; mainCamera.orthographicSize = CameraStartSize; mainCamera.transform.SetPositionAndRotation(new Vector3(0, CameraStartY, 0), Quaternion.Euler(rotEuler)); } else { // TODO: 这里的值是固定的,需要根据实际情况调整 //bottomMargin = 0.7f; mainCamera.orthographic = false; mainCamera.fieldOfView = 30; mainCamera.transform.SetPositionAndRotation(new Vector
if (GuideManager.Instance.IsGuiding) // 引导中禁止缩放
return;
//delta小于0是缩小
var zoomDelta = delta < 0 ? -ZoomStep : ZoomStep; //修改缩放值 ZoomScale += zoomDelta; AdjustSelf(); } public void KeepCenter(Vector3 centerPos) { var cacheTrans = mainCamera.transform; var oldPos = cacheTrans.position; oldPos.x = centerPos.x + 5f; oldPos.z = centerPos.z - 25f; // cacheTrans.position = oldPos; cacheTrans.DOMove(oldPos, 0.5f).OnUpdate(AdjustSelf); } Vector3 CalculateHitHorizontalPosition(Vector3 startPosition, Vector3 dir, float y) { if (dir.y == 0) return Vector3.zero; var p1 = startPosition; // 直线上一点 var v = dir; // 直线的方向向量 float x, z; // 已知直线上一点 p1(x1, y1, z1) 和 直线的方向向量 v(m, n, p) // 根据点向式 // (x - x1) / m = (y - y1) / n = (z - z1) / p // 有: // (x - p1.x) / v.x = (y - p1.y) / v.y = (z - p1.z) / v.z // 有: // x = p1.x + v.x * (y - p1.y) / v.y // z = p1.z + v.z * (y - p1.y) / v.y // 与平面 y = y 的交点坐标为 x = p1.x + v.x * (y - p1.y) / v.y; z = p1.z + v.z * (y - p1.y) / v.y; return new Vector3(x, y, z); } public void InitializeCameraPosition(Vector3 targetPosition) { var useOrthographic = PerformanceManager.instance != null && PerformanceManager.instance.data.fightUseOrthographic; var rotEuler = useOrthographic ? cameraStartRotationO : cameraStartRotationP; mainCamera.transform.SetPositionAndRotation( CalculateCell2CameraPosition(targetPosition), Quaternion.Euler(rotEuler)); AdjustSelf(); } private Vector3 CalculateCell2CameraPosition(Vector3 targetPosition) { var cameraTransform = mainCamera.transform; var startPosition = cameraTransform.position; var v = cameraTransform.forward; float x, z; z = targetPosition.z - v.z * (targetPosition.y - startPosition.y) / v.y; x = targetPosition.x - v.x * (targetPosition.y - startPosition.y) / v.y; return new Vector3(x, startPosition.y, z); } public void AdjustSelf() { mainCamera.transform.position = AdjustPosition(Size, out var isInsideBounds); } private Vector3 AdjustPosition(float size, out bool IsInsideBounds) { var position = transform.position; IsInsideBounds = true; var center = CalculateHitHorizontalPosition(position, transform.forward, 0); var left = center.x - leftMargin * size; var right = center.x + rightMargin * size; var top = center.z + topMargin * size; var bottom = center.z - bottomMargin * size; if (right - left < CameraBounds.max.x - CameraBounds.min.x) { if (left < CameraBounds.min.x) { center.x = CameraBounds.min.x + leftMargin * size; IsInsideBounds = false; } else if (right > CameraBounds.max.x) { center.x = CameraBounds.max.x - rightMargin * size; IsInsideBounds = false; } } else { center.x = CameraBounds.center.x; IsInsideBounds = false; } if (top - bottom < CameraBounds.max.z - CameraBounds.min.z) { if (bottom < CameraBounds.min.z) { center.z = CameraBounds.min.z + bottomMargin * size; IsInsideBounds = false; } else if (top > CameraBounds.max.z) { center.z = CameraBounds.max.z - topMargin * size; IsInsideBounds = false; } } else { center.z = CameraBounds.center.z; IsInsideBounds = false; } position = CalculateHitHorizontalPosition(center, transform.forward, position.y); return position; } private void OnDrawGizmos() { if (mainCamera != null)