144 lines
5.1 KiB
C#
144 lines
5.1 KiB
C#
|
|
using System;
|
|||
|
|
using UnityEngine;
|
|||
|
|
using Sirenix.OdinInspector;
|
|||
|
|
|
|||
|
|
[ExecuteAlways]
|
|||
|
|
public class CameraData : MonoBehaviour
|
|||
|
|
{
|
|||
|
|
public const float CameraStartY = 25;
|
|||
|
|
public const float CameraStartSize = 12;
|
|||
|
|
public float CameraStartFOV = 30;
|
|||
|
|
public const float NearClipPlane = 0.03f;
|
|||
|
|
public const float FarClipPlane = 150;
|
|||
|
|
public readonly Vector3 CameraStartRotationO = new Vector3(37.5f, -10f, 0f);
|
|||
|
|
public readonly Vector3 CameraStartRotationP = new Vector3(45, -10, 0);
|
|||
|
|
|
|||
|
|
//之前的缩放是6次滚轮从最小放到最大,故每一次缩放的值为1/6f
|
|||
|
|
public const float ZoomStep = 1 / 12f;
|
|||
|
|
|
|||
|
|
[Tooltip("控制缩放响应曲线")] public float zoomSensitivity = 2.0f;
|
|||
|
|
[Tooltip("缩放速度与当前缩放比例的关系系数")] public float zoomScaleFactor = 0.75f;
|
|||
|
|
[Tooltip("是否使用平滑缩放效果")] public bool smoothZoom = true;
|
|||
|
|
[ShowIf("smoothZoom")] public float zoomSmoothTime = 0.2f;
|
|||
|
|
|
|||
|
|
public float leftMargin = 1.5f;
|
|||
|
|
public float rightMargin = 1.5f;
|
|||
|
|
public float topMargin = 0.9f;
|
|||
|
|
public float bottomMargin = 0.9f;
|
|||
|
|
|
|||
|
|
[Header("Camera Movement Settings")] public float moveSpeedX = 0.19f;
|
|||
|
|
public float moveSpeedY = 0.3f;
|
|||
|
|
public float unitPerPixel = 0.01f;
|
|||
|
|
|
|||
|
|
[Tooltip("是否使用平滑移动效果")] public bool smoothPanning = false;
|
|||
|
|
|
|||
|
|
[ShowIf("smoothPanning")] [Tooltip("平移平滑时间,值越小响应越快")]
|
|||
|
|
public float panSmoothTime = 0.08f;
|
|||
|
|
|
|||
|
|
[ShowIf("smoothPanning")] [Tooltip("惯性系数,控制释放后继续滑动的距离")] [Range(0, 1)]
|
|||
|
|
public float panInertia = 0.8f;
|
|||
|
|
|
|||
|
|
[ShowIf("smoothPanning")] [Tooltip("最大平移速度限制")]
|
|||
|
|
public float maxPanSpeed = 3000f;
|
|||
|
|
|
|||
|
|
public float CameraMinSize = 6;
|
|||
|
|
public float CameraMaxSize = 12;
|
|||
|
|
public BoxCollider boxBounds;
|
|||
|
|
public float CameraMinFOV = 15;
|
|||
|
|
public float CameraMaxFOV = 30;
|
|||
|
|
|
|||
|
|
private Camera mainCamera;
|
|||
|
|
public Camera MainCamera => mainCamera;
|
|||
|
|
public Bounds CameraBounds { get; set; }
|
|||
|
|
|
|||
|
|
// 运行时配置
|
|||
|
|
public bool FingerMoveEnable { get; set; } = true;
|
|||
|
|
|
|||
|
|
// 对外提供是否使用正交相机的接口
|
|||
|
|
public bool UseOrthographicMode => CameraSettingsManager.CurrentSettings.UseOrthographicMode;
|
|||
|
|
|
|||
|
|
private void Awake()
|
|||
|
|
{
|
|||
|
|
mainCamera = GetComponent<Camera>();
|
|||
|
|
CameraBounds = boxBounds != null ? boxBounds.bounds : CameraBounds;
|
|||
|
|
|
|||
|
|
// 根据设置初始化相机
|
|||
|
|
InitializeCamera();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void InitializeCamera()
|
|||
|
|
{
|
|||
|
|
bool useOrthographic = UseOrthographicMode;
|
|||
|
|
|
|||
|
|
if (useOrthographic)
|
|||
|
|
{
|
|||
|
|
mainCamera.orthographic = true;
|
|||
|
|
mainCamera.orthographicSize = CameraStartSize;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
mainCamera.orthographic = false;
|
|||
|
|
mainCamera.fieldOfView = CameraStartFOV;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
mainCamera.nearClipPlane = NearClipPlane;
|
|||
|
|
mainCamera.farClipPlane = FarClipPlane;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void OnDrawGizmos()
|
|||
|
|
{
|
|||
|
|
if (mainCamera != null)
|
|||
|
|
{
|
|||
|
|
Gizmos.color = Color.red;
|
|||
|
|
var cameraTransform = transform;
|
|||
|
|
var position = cameraTransform.position;
|
|||
|
|
float size = IsOrthographic ? mainCamera.orthographicSize :
|
|||
|
|
mainCamera.fieldOfView * (CameraMaxSize - CameraMinSize) / (CameraMaxFOV - CameraMinFOV);
|
|||
|
|
|
|||
|
|
var center = CalculateHitHorizontalPosition(position, cameraTransform.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;
|
|||
|
|
|
|||
|
|
Gizmos.DrawLineList(new ReadOnlySpan<Vector3>(new[]
|
|||
|
|
{
|
|||
|
|
new Vector3(left, 0.5f, top), new Vector3(left, 0.5f, bottom),
|
|||
|
|
new Vector3(left, 0.5f, bottom), new Vector3(right, 0.5f, bottom),
|
|||
|
|
new Vector3(right, 0.5f, bottom), new Vector3(right, 0.5f, top),
|
|||
|
|
new Vector3(right, 0.5f, top), new Vector3(left, 0.5f, top),
|
|||
|
|
}
|
|||
|
|
)
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CameraBounds = boxBounds == null ? CameraBounds : boxBounds.bounds;
|
|||
|
|
Gizmos.DrawWireCube(CameraBounds.center, CameraBounds.size);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public bool IsOrthographic => mainCamera.orthographic;
|
|||
|
|
|
|||
|
|
public 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);
|
|||
|
|
}
|
|||
|
|
}
|