234 lines
8.2 KiB
C#
234 lines
8.2 KiB
C#
using Base;
|
||
using UnityEngine;
|
||
using UnityEngine.SceneManagement;
|
||
|
||
namespace CameraControl
|
||
{
|
||
public class CameraControl : Utils.MonoSingleton<CameraControl>, ITick, ITickUI
|
||
{
|
||
// Camera movement variables
|
||
[SerializeField] private float _zoomSpeed = 5f;
|
||
[SerializeField] private float _minZoom = 2f;
|
||
[SerializeField] private float _maxZoom = 20f;
|
||
[SerializeField] private float _focusLerpSpeed = 5f;
|
||
|
||
private Vector3 _dragOrigin;
|
||
private bool _isDragging = false;
|
||
|
||
private Camera _camera;
|
||
|
||
private int dimensionId;
|
||
private string[] dimensionList;
|
||
|
||
|
||
private void OnDestroy()
|
||
{
|
||
// 移除事件监听
|
||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||
}
|
||
|
||
protected override void OnStart()
|
||
{
|
||
// 注册场景加载事件。请注意,MonoSingleton中的OnStart通常由Awake调用。
|
||
// 真正的Init调用已移至Start方法,以确保Program.Instance已完成其Awake阶段的初始化。
|
||
SceneManager.sceneLoaded += OnSceneLoaded;
|
||
}
|
||
|
||
private void Start()
|
||
{
|
||
// 在Start中调用Init,确保所有依赖的单例(如Program.Instance)已完成Awake阶段的初始化。
|
||
Init();
|
||
}
|
||
|
||
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
||
{
|
||
// 场景加载完成后调用 Init 方法,重新获取相机引用并初始化维度状态。
|
||
// 这确保了如果CameraControl是DontDestroyOnLoad,在切换场景后也能正确工作。
|
||
Init();
|
||
}
|
||
|
||
|
||
private void Init()
|
||
{
|
||
// 确保相机引用有效
|
||
if (_camera == null)
|
||
{
|
||
_camera = Camera.main;
|
||
if (_camera == null)
|
||
{
|
||
_camera = FindFirstObjectByType<Camera>();
|
||
}
|
||
}
|
||
|
||
if (_camera == null)
|
||
{
|
||
Debug.LogError("No Camera found in the scene! CameraControl functionalities will be limited.");
|
||
return; // 如果没有相机,则无法进行后续初始化
|
||
}
|
||
|
||
// 初始化维度数据 (假设 Program.Instance 总是已初始化)
|
||
dimensionId = 0; // 默认从第一个维度开始
|
||
dimensionList = Program.Instance.Dimensions;
|
||
if (dimensionList != null && dimensionList.Length > 0)
|
||
{
|
||
SetCameraPositionForDimension(0);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning("Dimension list is empty or null from Program.Instance. Cannot set initial camera position for dimensions.");
|
||
}
|
||
}
|
||
|
||
public void NextDimension()
|
||
{
|
||
if (_camera == null)
|
||
{
|
||
Debug.LogWarning("Camera reference is null, cannot switch dimensions.");
|
||
return;
|
||
}
|
||
if (dimensionList == null || dimensionList.Length == 0)
|
||
{
|
||
Debug.LogWarning("Dimension list is empty.");
|
||
return;
|
||
}
|
||
|
||
// 1. 保存当前相机的真实位置到当前维度 (假设 Program.Instance 总是已初始化)
|
||
// 维度ID范围检查仍然保留,因为这是数组访问的安全保障
|
||
if (dimensionId >= 0 && dimensionId < dimensionList.Length)
|
||
{
|
||
// Program.Instance 假设不会为 null
|
||
var currentDimension = Program.Instance.GetDimension(dimensionList[dimensionId]);
|
||
if (currentDimension != null)
|
||
{
|
||
currentDimension.cameraPosition = _camera.transform.position;
|
||
// Debug.Log($"Saved camera position {currentDimension.cameraPosition} for dimension {dimensionList[dimensionId]} (ID: {dimensionId})");
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning($"Could not find dimension object for ID {dimensionId} ({dimensionList[dimensionId]}) to save camera position.");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning($"Current dimensionId ({dimensionId}) is out of bounds for saving camera position (dimensionList length: {dimensionList.Length}).");
|
||
}
|
||
|
||
// 2. 更新 dimensionId,形成循环
|
||
dimensionId = (dimensionId + 1) % dimensionList.Length;
|
||
|
||
// 3. 更新相机位置到新维度
|
||
SetCameraPositionForDimension(dimensionId);
|
||
}
|
||
|
||
private void SetCameraPositionForDimension(int id)
|
||
{
|
||
if (_camera == null)
|
||
{
|
||
Debug.LogWarning("Camera reference is null, cannot set camera position.");
|
||
return;
|
||
}
|
||
if (dimensionList == null || id < 0 || id >= dimensionList.Length)
|
||
{
|
||
Debug.LogWarning($"Dimension ID {id} is out of bounds or dimension list is null/empty.");
|
||
return;
|
||
}
|
||
// Program.Instance 假设不会为 null
|
||
|
||
// 确保获取到的 Dimension 对象不为 null
|
||
var dimension = Program.Instance.GetDimension(dimensionList[id]);
|
||
if (dimension)
|
||
{
|
||
Vector3 cameraPosition = dimension.cameraPosition;
|
||
_camera.transform.position = cameraPosition;
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning($"Dimension object for ID {id} ({dimensionList[id]}) is null. Cannot set camera position.");
|
||
}
|
||
}
|
||
|
||
public void Tick()
|
||
{
|
||
if (_camera == null) return; // 确保相机存在
|
||
|
||
// 假设 Program.Instance 总是已初始化
|
||
if (Program.Instance.FocusedEntity)
|
||
{
|
||
var targetPosition = new Vector3(
|
||
Program.Instance.FocusedEntity.Position.x,
|
||
Program.Instance.FocusedEntity.Position.y,
|
||
_camera.transform.position.z);
|
||
|
||
// 使用 deltaTime 进行平滑的相机跟随
|
||
_camera.transform.position = Vector3.Lerp(
|
||
_camera.transform.position,
|
||
targetPosition,
|
||
Time.deltaTime * _focusLerpSpeed);
|
||
}
|
||
|
||
if (Input.GetKeyDown(KeyCode.Tab))
|
||
{
|
||
NextDimension();
|
||
}
|
||
}
|
||
|
||
public void TickUI()
|
||
{
|
||
if (!_camera) // 确保相机存在
|
||
return;
|
||
|
||
HandleMiddleMouseDrag();
|
||
// HandleMouseZoom();
|
||
}
|
||
|
||
public void SetPosition(Vector3 position)
|
||
{
|
||
if (_camera)
|
||
_camera.transform.position = position;
|
||
else
|
||
Debug.LogWarning("Camera reference is null, cannot set position.");
|
||
}
|
||
|
||
private void HandleMiddleMouseDrag()
|
||
{
|
||
if (_camera == null) return; // 确保相机存在
|
||
|
||
// Start drag
|
||
if (Input.GetMouseButtonDown(2)) // Middle mouse button
|
||
{
|
||
_dragOrigin = _camera.ScreenToWorldPoint(Input.mousePosition);
|
||
_isDragging = true;
|
||
// 假设 Program.Instance 总是已初始化
|
||
if (Program.Instance.FocusedEntity)
|
||
{
|
||
Program.Instance.FocusedEntity.PlayerControlled = false;
|
||
Program.Instance.SetFocusedEntity(null);
|
||
}
|
||
}
|
||
|
||
// During drag
|
||
if (Input.GetMouseButton(2) && _isDragging)
|
||
{
|
||
var difference = _dragOrigin - _camera.ScreenToWorldPoint(Input.mousePosition);
|
||
_camera.transform.position += difference;
|
||
}
|
||
|
||
// End drag
|
||
if (Input.GetMouseButtonUp(2))
|
||
{
|
||
_isDragging = false;
|
||
}
|
||
}
|
||
|
||
private void HandleMouseZoom()
|
||
{
|
||
if (_camera == null) return; // 确保相机存在
|
||
|
||
var scroll = Input.GetAxis("Mouse ScrollWheel");
|
||
if (scroll == 0) return;
|
||
var newSize = _camera.orthographicSize - scroll * _zoomSpeed;
|
||
_camera.orthographicSize = Mathf.Clamp(newSize, _minZoom, _maxZoom);
|
||
}
|
||
}
|
||
}
|