Files
Gen_Hack-and-Slash-Roguelite/Client/Assets/Scripts/CameraControl/CameraControl.cs

234 lines
8.2 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 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);
}
}
}