using Base; using UnityEngine; using UnityEngine.SceneManagement; namespace CameraControl { public class CameraControl : Utils.MonoSingleton, 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(); } } 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); } } }