(client) feat:UI更新 chore:LogUI性能更好,并且修复反复打开Log消失的bug,删除部分非预期的警告

This commit is contained in:
m0_75251201
2025-08-30 00:26:27 +08:00
parent 34abe845b1
commit 7252698764
58 changed files with 4849 additions and 508 deletions

View File

@ -19,41 +19,61 @@ namespace CameraControl
private Vector3 _dragOrigin; // 拖拽操作的起始世界坐标
private bool _isDragging; // 标记摄像机是否正在被拖拽
private Camera _camera; // 当前场景中的主摄像机引用
private Camera _cachedCamera; // 缓存的场景摄像机引用
/// <summary>
/// 获取当前生效的场景摄像机。懒加载并缓存。
/// </summary>
public Camera CurrentCamera
{
get
{
if (!_cachedCamera)
{
Debug.Log("[CameraControl] Attempting to get main camera...");
_cachedCamera = Camera.main; // 尝试获取主摄像机
if (!_cachedCamera) // 如果主摄像机不存在或未标记,则尝试查找场景中的第一个摄像机
{
Debug.LogWarning("[CameraControl] Main camera not found, attempting to find first object of type Camera.");
_cachedCamera = FindFirstObjectByType<Camera>();
}
if (!_cachedCamera)
{
Debug.LogError("[CameraControl] No available camera found in scene! CameraControl functionality will be limited.");
}
else
{
Debug.Log($"[CameraControl] Camera cached: {_cachedCamera.name}");
}
}
return _cachedCamera;
}
}
private int dimensionId; // 当前摄像机控制器关注的维度索引
private string[] dimensionList; // 维度名称列表
/// <summary>
/// MonoSingleton 的 OnStart 方法,在单例首次创建并激活时调用,早于普通的 Start 方法。
/// 用于初始化摄像机缓存。
/// </summary>
protected override void OnStart()
{
Debug.Log("[CameraControl] OnStart called. Subscribing to OnFocusedDimensionChanged event.");
Program.Instance.OnFocusedDimensionChanged += Init;
}
/// <summary>
/// 当脚本实例被销毁时调用。
/// 用于取消订阅 Program.Instance 的事件,防止内存泄漏。
/// </summary>
private void OnDestroy()
{
// 在OnDestroy时进行Program.Instance检查是合理的因为Program实例可能已被销毁。
if (Program.Instance != null)
{
Program.Instance.OnFocusedDimensionChanged -= Init;
}
Debug.Log("[CameraControl] OnDestroy called. Unsubscribing from OnFocusedDimensionChanged event.");
Program.Instance.OnFocusedDimensionChanged -= Init;
}
/// <summary>
/// 脚本实例在第一次帧更新之前被启用时调用。
/// 用于订阅 Program.Instance 的事件,并进行初始设置。
/// </summary>
private void Start()
{
// 在Start时进行Program.Instance检查是合理的防止CameraControl比Program实例更早启动。
if (Program.Instance != null)
{
Program.Instance.OnFocusedDimensionChanged += Init; // 订阅聚焦维度改变事件
Init(); // 首次调用初始化,根据当前聚焦维度设置摄像机状态
}
else
{
Debug.LogError("CameraControl 的 Start 方法中 Program.Instance 为空。请检查 Program 单例的初始化顺序。摄像机控制功能将无法初始化。");
}
}
/// <summary>
/// 根据指定的维度对象初始化摄像机控制器。
@ -62,36 +82,21 @@ namespace CameraControl
/// <param name="obj">当前聚焦的维度对象。</param>
private void Init(Dimension obj)
{
// 修改点 1: 统一 Unity 对象 `null` 检查,移除冗余 `_camera == null`
// 确保相机引用有效,如果为空则尝试获取主相机
if (!_camera)
{
_camera = Camera.main;
if (!_camera) // 再次检查获取是否成功
{
_camera = FindFirstObjectByType<Camera>();
}
}
Debug.Log($"[CameraControl] Init(Dimension obj) called. Focused Dimension: {(obj != null ? obj.name : "null")}");
if (!_camera) // 如果到此为止仍未获取到相机,记录错误并返回
dimensionList = Program.Instance.Dimensions;
Debug.Log($"[CameraControl] Dimension list updated. Count: {(dimensionList != null ? dimensionList.Length.ToString() : "null")}");
if (!CurrentCamera) // 如果摄像机仍未找到,记录错误并返回
{
Debug.LogError("场景中未找到摄像机!CameraControl 功能将无法完全初始化。");
// 如果没有相机,后续依赖相机的逻辑都无法执行,直接返回。
// dimensionList 的获取如果逻辑上不依赖相机,可以放在此处之外。
// 但当前上下文中Init的主要目的是初始化相机视角等无相机则无意义。
Debug.LogError("[CameraControl] No camera found! CameraControl functionality will not be fully initialized.");
return;
}
// 修改点 2: 移除对 `Program.Instance` 的冗余 `null` 检查
// 修改点 3: `Init` 方法中 `dimensionList` 的获取位置
// 总是获取最新的维度列表,因为外部维度状态可能会变化
dimensionList = Program.Instance.Dimensions;
// 处理 obj 为 null 的情况
// 处理 obj 为 null 的情况 - 此时 dimensionList 已更新
if (!obj)
{
Debug.LogWarning("Init 方法在聚焦维度为空的情况下被调用。维度列表已更新,但摄像机状态未根据特定维度设置。");
// 此时 dimensionId 仍然是默认值或上次设置的值,不进行 cameraPosition 的设置。
Debug.LogWarning("[CameraControl] Init method called with a null focused dimension. Dimension list updated, but camera state not set based on a specific dimension.");
return;
}
@ -100,15 +105,24 @@ namespace CameraControl
if (focusedIndex != -1)
{
dimensionId = focusedIndex;
Debug.Log($"[CameraControl] Focused dimension '{obj.name}' found at index {dimensionId}.");
}
else
{
Debug.LogWarning($"聚焦维度 '{obj.name}' 未在维度列表中找到。回退到 ID 0");
Debug.LogWarning($"[CameraControl] Focused dimension '{obj.name}' not found in the dimension list. Falling back to ID 0.");
dimensionId = 0; // 找不到时,回退到第一个维度,避免数组越界
}
// 设置摄像机位置到当前聚焦维度的位置 (移除 Program.Instance 的 null 检查)
_camera.transform.position = Program.Instance.FocusedDimension.cameraPosition;
// 设置摄像机位置到当前聚焦维度的位置
if (Program.Instance.FocusedDimension != null)
{
CurrentCamera.transform.position = Program.Instance.FocusedDimension.cameraPosition;
Debug.Log($"[CameraControl] Camera position set to focused dimension's camera position: {CurrentCamera.transform.position}");
}
else
{
Debug.LogWarning("[CameraControl] Focused dimension is null when trying to set camera position. Camera position not explicitly updated based on a dimension.");
}
}
/// <summary>
@ -116,7 +130,7 @@ namespace CameraControl
/// </summary>
private void Init()
{
// 移除 Program.Instance 的 null 检查
Debug.Log("[CameraControl] Init() called (no parameters). Calling Init(Program.Instance.FocusedDimension).");
Init(Program.Instance.FocusedDimension);
}
@ -126,41 +140,44 @@ namespace CameraControl
/// </summary>
public void NextDimension()
{
// 修改点 1: 统一 Unity 对象 `null` 检查
if (!_camera)
Debug.Log("[CameraControl] NextDimension called.");
if (!CurrentCamera)
{
Debug.LogWarning("摄像机引用为空,无法切换维度。");
Debug.LogWarning("[CameraControl] Camera reference is null, cannot switch dimensions.");
return;
}
if (dimensionList == null || dimensionList.Length == 0)
{
Debug.LogWarning("维度列表为空。");
Debug.LogWarning("[CameraControl] Dimension list is empty or uninitialized, cannot switch dimensions.");
return;
}
// 1. 保存当前摄像机的实际位置到当前维度 (移除 Program.Instance 的 null 检查)
// 1. 保存当前摄像机的实际位置到当前维度
if (dimensionId >= 0 && dimensionId < dimensionList.Length)
{
var currentDimension = Program.Instance.GetDimension(dimensionList[dimensionId]);
if (currentDimension != null) // currentDimension 可能是普通 C# 对象,所以此处 null 检查是必要的
if (currentDimension != null)
{
currentDimension.cameraPosition = _camera.transform.position;
currentDimension.cameraPosition = CurrentCamera.transform.position;
Debug.Log($"[CameraControl] Saved current camera position {CurrentCamera.transform.position} to dimension '{dimensionList[dimensionId]}'.");
}
else
{
Debug.LogWarning($"无法找到 ID 为 {dimensionId} ({dimensionList[dimensionId]}) 的维度对象,无法保存摄像机位置。");
Debug.LogWarning($"[CameraControl] Could not find Dimension object for ID {dimensionId} ({dimensionList[dimensionId]}), cannot save camera position.");
}
}
else
{
Debug.LogWarning($"当前维度ID ({dimensionId}) 超出范围,无法保存摄像机位置 (维度列表长度: {dimensionList.Length})");
Debug.LogWarning($"[CameraControl] Current dimension ID ({dimensionId}) is out of range, cannot save camera position (Dimension list length: {dimensionList.Length}).");
}
// 2. 更新 dimensionId形成循环切换
// 2. 更新 dimensionId, 形成循环切换
dimensionId = (dimensionId + 1) % dimensionList.Length;
Debug.Log($"[CameraControl] Updated dimensionId to {dimensionId}.");
// 3. 更新聚焦维度,摄像机位置的更新将由事件触发的 Init 方法处理
SetCameraPositionForDimension(dimensionId);
SetFocusedDimensionById(dimensionId);
}
/// <summary>
@ -168,21 +185,22 @@ namespace CameraControl
/// 摄像机位置的实际更新将通过 Program.Instance.OnFocusedDimensionChanged 事件在 Init(Dimension obj) 方法中处理。
/// </summary>
/// <param name="id">要设置的维度ID。</param>
private void SetCameraPositionForDimension(int id)
private void SetFocusedDimensionById(int id)
{
// 修改点 1: 统一 Unity 对象 `null` 检查
if (!_camera)
Debug.Log($"[CameraControl] SetFocusedDimensionById called with ID: {id}.");
if (!CurrentCamera)
{
Debug.LogWarning("摄像机引用为空,无法设置摄像机位置。");
Debug.LogWarning("[CameraControl] Camera reference is null, cannot set camera position.");
return;
}
if (dimensionList == null || id < 0 || id >= dimensionList.Length)
{
Debug.LogWarning($"维度ID {id} 超出范围或维度列表为空。");
Debug.LogWarning($"[CameraControl] Dimension ID {id} is out of range or dimension list is empty, cannot set focused dimension.");
return;
}
// 移除 Program.Instance 的 null 检查
Program.Instance.SetFocusedDimension(dimensionList[id]);
Debug.Log($"[CameraControl] Program.Instance.SetFocusedDimension called for '{dimensionList[id]}'.");
}
/// <summary>
@ -190,20 +208,19 @@ namespace CameraControl
/// </summary>
public void Tick()
{
// 修改点 1: 统一 Unity 对象 `null` 检查
if (!_camera) return; // 确保相机存在
if (!CurrentCamera) return; // 确保相机存在
// 当没有拖拽且存在聚焦实体时,摄像机跟随聚焦实体 (移除 Program.Instance 的 null 检查)
// 当没有拖拽且存在聚焦实体时,摄像机跟随聚焦实体
if (!_isDragging && Program.Instance.FocusedEntity)
{
var targetPosition = new Vector3(
Program.Instance.FocusedEntity.Position.x,
Program.Instance.FocusedEntity.Position.y,
_camera.transform.position.z);
CurrentCamera.transform.position.z);
// 使用 deltaTime 进行平滑的摄像机跟随
_camera.transform.position = Vector3.Lerp(
_camera.transform.position,
CurrentCamera.transform.position = Vector3.Lerp(
CurrentCamera.transform.position,
targetPosition,
Time.deltaTime * _focusLerpSpeed);
}
@ -211,6 +228,7 @@ namespace CameraControl
// 按下 Tab 键时切换到下一个维度
if (Input.GetKeyDown(KeyCode.Tab))
{
Debug.Log("[CameraControl] Tab key pressed. Calling NextDimension().");
NextDimension();
}
}
@ -220,8 +238,7 @@ namespace CameraControl
/// </summary>
public void TickUI()
{
// 修改点 1: 统一 Unity 对象 `null` 检查
if (!_camera) // 确保相机存在
if (!CurrentCamera) // 确保相机存在
return;
HandleMiddleMouseDrag(); // 处理鼠标中键拖拽
@ -234,11 +251,15 @@ namespace CameraControl
/// <param name="position">要设置的摄像机位置。</param>
public void SetPosition(Vector3 position)
{
// 修改点 1: 统一 Unity 对象 `null` 检查
if (_camera) // if (!_camera) 比 if (_camera == null) 更优雅
_camera.transform.position = position;
if (CurrentCamera)
{
CurrentCamera.transform.position = position;
Debug.Log($"[CameraControl] Camera position explicitly set to: {position}.");
}
else
Debug.LogWarning("摄像机引用为空,无法设置位置。");
{
Debug.LogWarning("[CameraControl] Camera reference is null, cannot set position.");
}
}
/// <summary>
@ -246,17 +267,18 @@ namespace CameraControl
/// </summary>
private void HandleMiddleMouseDrag()
{
// 修改点 1: 统一 Unity 对象 `null` 检查
if (!_camera) return; // 确保相机存在
if (!CurrentCamera) return; // 确保相机存在
// 开始拖拽:检测鼠标中键按下
if (Input.GetMouseButtonDown(2)) // 鼠标中键
{
_dragOrigin = _camera.ScreenToWorldPoint(Input.mousePosition);
_dragOrigin = CurrentCamera.ScreenToWorldPoint(Input.mousePosition);
_isDragging = true;
// 如果有聚焦实体,则在开始拖拽时取消聚焦,暂停跟随 (移除 Program.Instance 的 null 检查)
Debug.Log($"[CameraControl] Mouse middle button down. Starting drag from world point: {_dragOrigin}.");
// 如果有聚焦实体,则在开始拖拽时取消聚焦,暂停跟随
if (Program.Instance.FocusedEntity)
{
Debug.Log("[CameraControl] Focused entity detected. Setting FocusedEntity to null to pause follow.");
Program.Instance.SetFocusedEntity(null);
}
}
@ -264,15 +286,15 @@ namespace CameraControl
// 拖拽中:根据鼠标移动更新摄像机位置
if (Input.GetMouseButton(2) && _isDragging)
{
var difference = _dragOrigin - _camera.ScreenToWorldPoint(Input.mousePosition);
_camera.transform.position += difference;
var difference = _dragOrigin - CurrentCamera.ScreenToWorldPoint(Input.mousePosition);
CurrentCamera.transform.position += difference;
}
// 结束拖拽:检测鼠标中键抬起
if (Input.GetMouseButtonUp(2))
{
_isDragging = false;
// 拖拽结束后,当前代码不会自动重新聚焦实体。如果需要此行为,应在此处添加逻辑。
Debug.Log("[CameraControl] Mouse middle button up. Dragging ended.");
}
}
@ -281,23 +303,15 @@ namespace CameraControl
/// </summary>
private void HandleMouseZoom()
{
// 修改点 1: 统一 Unity 对象 `null` 检查
if (!_camera) return; // 确保相机存在
if (!CurrentCamera) return; // 确保相机存在
var scroll = Input.GetAxis("Mouse ScrollWheel");
if (scroll == 0) return; // 没有滚轮滚动,则返回
// 根据滚轮输入调整正交摄像机的尺寸,并限制在最小和最大缩放之间
var newSize = _camera.orthographicSize - scroll * _zoomSpeed;
_camera.orthographicSize = Mathf.Clamp(newSize, _minZoom, _maxZoom);
}
/// <summary>
/// MonoSingleton 的 OnStart 方法,可在单例首次创建时添加额外初始化逻辑。
/// </summary>
protected override void OnStart()
{
// 当前为空,是合理的。
var newSize = CurrentCamera.orthographicSize - scroll * _zoomSpeed;
CurrentCamera.orthographicSize = Mathf.Clamp(newSize, _minZoom, _maxZoom);
// Debug.Log($"[CameraControl] Mouse scroll wheel. New orthographicSize: {CurrentCamera.orthographicSize}"); // Too frequent for general logging
}
}
}