TH1/Unity/Assets/Scripts/TH1_UI/CameraController.cs
2025-10-27 20:52:24 +08:00

257 lines
8.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using RuntimeData;
using TH1_Logic.Core;
public class CameraController : MonoBehaviour
{
public float zoomSpeed = 5f; // 滚轮缩放速度
public float minZoom = 3f; // 最小缩放值
public float maxZoom = 15f; // 最大缩放值
public float panSpeed = 0.5f; // 拖动地图的速度
//相机移动上下边界
public float minX = -200f;
public float maxX = 200f;
public float minY = -60f;
public float maxY = 230f;
//相机移动动画相关参数
public float moveSpeed = 0.5f; // 平滑移动速度
private Vector3? _smoothTargetPosition = null; //记录相机平滑移动的起点
private Vector3 _startPos;
private float _moveProgress = 0f;
private float _moveDuration; // 可调节移动总时长
private bool _isMoving = false;
private const float TARGET_ASPECT = 16f / 9f; // 目标宽高比
private Camera _camera;
private int _lastWidth, _lastHeight;
void Start()
{
_camera = GetComponent<Camera>();
UpdateViewport();
}
void Update()
{
HandleSmoothMove();
HandleZoom();
if (Screen.width != _lastWidth || Screen.height != _lastHeight)
UpdateViewport();
//if (_camera.orthographic) _camera.orthographicSize = 20f;
}
private void LateUpdate()
{
HandlePan();
}
void UpdateViewport()
{
float currentAspect = (float)Screen.width / Screen.height;
Rect rect = new Rect(0, 0, 1, 1); // 默认全屏
if (currentAspect > TARGET_ASPECT)
{
// 窗口过宽:左右黑边
rect.width = TARGET_ASPECT / currentAspect;
rect.x = (1f - rect.width) / 2f;
}
else if (currentAspect < TARGET_ASPECT)
{
// 窗口过高:上下黑边
rect.height = currentAspect / TARGET_ASPECT;
rect.y = (1f - rect.height) / 2f;
}
_camera.rect = rect; // 应用视口矩形
_lastWidth = Screen.width;
_lastHeight = Screen.height;
}
void HandleSmoothMove()
{
if (!UIBlockCameraDrag.MoveEvent && _isMoving && _smoothTargetPosition.HasValue)
{
_moveProgress += Time.deltaTime / _moveDuration;
float t = Mathf.SmoothStep(0, 1, _moveProgress); // 缓动曲线
Vector3 targetPos = _smoothTargetPosition.Value;
Camera.main.transform.position = Vector3.Lerp(_startPos, targetPos, t);
if (_moveProgress >= 1f)
{
Camera.main.transform.position = targetPos;
_smoothTargetPosition = null;
_isMoving = false;
}
}
}
void HandleZoom()
{
// 获取滚轮输入
float scroll = Input.GetAxis("Mouse ScrollWheel");
if (scroll != 0f)
{
Camera.main.orthographicSize -= scroll * zoomSpeed;
Camera.main.orthographicSize = Mathf.Clamp(Camera.main.orthographicSize, minZoom, maxZoom);
}
}
void CameraMove(Vector3 deltaVector)
{
Vector3 targetPosition = Camera.main.transform.position + deltaVector;
// 计算当前相机视野的一半宽高
float vertExtent = Camera.main.orthographicSize;
float horzExtent = vertExtent * Camera.main.aspect;
// 限制相机的中心点,使得视野边缘不超出边界
float minXClamp = minX + horzExtent;
float maxXClamp = maxX - horzExtent;
float minYClamp = minY + vertExtent;
float maxYClamp = maxY - vertExtent;
targetPosition.x = Mathf.Clamp(targetPosition.x, minXClamp, maxXClamp);
targetPosition.y = Mathf.Clamp(targetPosition.y, minYClamp, maxYClamp);
Camera.main.transform.position = targetPosition;
}
void HandlePan()
{
if (UIBlockCameraDrag.MoveEvent)
{
CameraMove(UIBlockCameraDrag.MoveVector);
/*Vector3 targetPosition = Camera.main.transform.position + ;
// 计算当前相机视野的一半宽高
float vertExtent = Camera.main.orthographicSize;
float horzExtent = vertExtent * Camera.main.aspect;
// 限制相机的中心点,使得视野边缘不超出边界
float minXClamp = minX + horzExtent;
float maxXClamp = maxX - horzExtent;
float minYClamp = minY + vertExtent;
float maxYClamp = maxY - vertExtent;
targetPosition.x = Mathf.Clamp(targetPosition.x, minXClamp, maxXClamp);
targetPosition.y = Mathf.Clamp(targetPosition.y, minYClamp, maxYClamp);
Camera.main.transform.position = targetPosition;*/
UIBlockCameraDrag.DragOrigin = Camera.main.ScreenToWorldPoint(Input.mousePosition);
}
else if (Main.Instance.InputLogic!= null && Main.Instance.InputLogic.WASDMapMover)
{
Main.Instance.InputLogic.WASDMapMover = false;
CameraMove(Main.Instance.InputLogic.WASDMapMoverVector);
}
}
public void CameraFocusOnGrid(GridData gridData, bool Center = false)
{
Vector3 worldPosition = Table.Instance.GridToWorld(gridData);
float vertExtent = Camera.main.orthographicSize;
float horzExtent = vertExtent * Camera.main.aspect;
_moveDuration = Table.Instance.AnimDataAssets.AIAnimCameraMoveTime;
//瞬间移到中心
if (Center)
{
float clampedX = Mathf.Clamp(worldPosition.x, minX + horzExtent, maxX - horzExtent);
float clampedY = Mathf.Clamp(worldPosition.y, minY + vertExtent, maxY - vertExtent);
Vector3 finalTarget = new Vector3(clampedX, clampedY, Camera.main.transform.position.z);
_startPos = Camera.main.transform.position;
_smoothTargetPosition = finalTarget;
_moveProgress = 0f;
_isMoving = true;
}
//平滑移动到视觉框内
else
{
Vector3 camPos = Camera.main.transform.position;
// 获取世界坐标 → 屏幕坐标
Vector3 screenPos = Camera.main.WorldToScreenPoint(worldPosition);
float screenWidth = Screen.width;
float screenHeight = Screen.height;
// 原始区域尺寸
float boxWidth = 1400f;
float boxHeight = 600f;
// 削减左侧150像素后的区域
float reducedLeft = 550f;
//如果是AI行动给画面中心位置
if (!Main.MapData.CurPlayer?.IsSelfPlayer() ?? false)
{
boxWidth = 400f;
boxHeight = 200f;
reducedLeft = 0f;
}
float adjustedBoxWidth = boxWidth - reducedLeft;
float xMax = (screenWidth + boxWidth) / 2f; // 保持右侧不变
float xMin = xMax - adjustedBoxWidth; // 左侧往右收缩150像素
float yMin = (screenHeight - boxHeight) / 2f;
float yMax = (screenHeight + boxHeight) / 2f;
// 如果点已经在框中,不动
if (screenPos.x >= xMin && screenPos.x <= xMax &&
screenPos.y >= yMin && screenPos.y <= yMax)
{
return;
}
// 计算目标点应该在屏幕中央框内的“目标屏幕位置”
float targetScreenX = Mathf.Clamp(screenPos.x, xMin, xMax);
float targetScreenY = Mathf.Clamp(screenPos.y, yMin, yMax);
Vector3 desiredScreenPos = new Vector3(targetScreenX, targetScreenY, screenPos.z);
// 将这个屏幕位置转回世界空间
Vector3 desiredWorldPos = Camera.main.ScreenToWorldPoint(desiredScreenPos);
// 计算需要相机移动的 delta = 当前格子位置 - 应该出现在的位置
Vector3 offset = worldPosition - desiredWorldPos;
Vector3 targetPos = camPos + offset;
// 限制相机移动范围
vertExtent = Camera.main.orthographicSize;
horzExtent = vertExtent * Camera.main.aspect;
float minXClamp = minX + horzExtent;
float maxXClamp = maxX - horzExtent;
float minYClamp = minY + vertExtent;
float maxYClamp = maxY - vertExtent;
targetPos.x = Mathf.Clamp(targetPos.x, minXClamp, maxXClamp);
targetPos.y = Mathf.Clamp(targetPos.y, minYClamp, maxYClamp);
// 平滑移动
_startPos = camPos;
_smoothTargetPosition = new Vector3(targetPos.x, targetPos.y, camPos.z);
_moveProgress = 0f;
_isMoving = true;
}
}
}