2025-08-25 18:24:12 +08:00
|
|
|
|
using Managers;
|
2025-08-24 17:15:52 +08:00
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
namespace Map
|
|
|
|
|
{
|
2025-08-25 18:24:12 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 表示游戏中的一个维度或场景区域。
|
|
|
|
|
/// 实体管理器将根据此维度来组织和管理实体。
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class Dimension : MonoBehaviour
|
2025-08-24 17:15:52 +08:00
|
|
|
|
{
|
2025-08-25 18:24:12 +08:00
|
|
|
|
[SerializeField] private bool defaultOpen = false;
|
|
|
|
|
|
|
|
|
|
[SerializeField] [Tooltip("此维度的唯一标识符。如果为空,将使用GameObject的名称。")]
|
|
|
|
|
private string _dimensionId;
|
|
|
|
|
|
|
|
|
|
[SerializeField] public MapGenerator mapGenerator;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取此维度的唯一标识符。
|
|
|
|
|
/// </summary>
|
|
|
|
|
public string DimensionId
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(_dimensionId))
|
|
|
|
|
{
|
|
|
|
|
_dimensionId = gameObject.name; // 如果未设置,默认使用GameObject名称
|
|
|
|
|
Debug.LogWarning(
|
|
|
|
|
$"Dimension ID not explicitly set for {gameObject.name}. Using GameObject name as ID: {_dimensionId}",
|
|
|
|
|
this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return _dimensionId;
|
|
|
|
|
}
|
|
|
|
|
// 内部设置器,允许在Awake中初始化或编辑器中赋值
|
|
|
|
|
private set => _dimensionId = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 此维度下所有实体的根Transform。用于组织场景层级。
|
|
|
|
|
/// </summary>
|
|
|
|
|
public Transform DimensionRoot { get; private set; }
|
|
|
|
|
|
|
|
|
|
private void Awake()
|
|
|
|
|
{
|
|
|
|
|
// 1. 确保 DimensionId 已初始化,这会触发 DimensionId 属性的 getter 逻辑
|
|
|
|
|
var id = DimensionId;
|
|
|
|
|
// 2. 创建一个用于存放此维度下所有实体的根GameObject,方便管理
|
|
|
|
|
var rootObj = new GameObject($"_Entities_{id}");
|
|
|
|
|
rootObj.transform.SetParent(this.transform); // 将其作为Dimension对象的子对象
|
|
|
|
|
DimensionRoot = rootObj.transform;
|
|
|
|
|
// 3. 注册此维度到 Program
|
|
|
|
|
if (Program.Instance != null) // 检查单例是否仍然存在
|
|
|
|
|
{
|
|
|
|
|
Program.Instance.RegisterDimension(this);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError(
|
|
|
|
|
"[Dimension] Program.Instance is null during Dimension Awake. Cannot register dimension.", this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4. 注册此维度到 EntityManage
|
|
|
|
|
if (EntityManage.Instance != null)
|
|
|
|
|
{
|
|
|
|
|
EntityManage.Instance.RegisterDimension(this);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Debug.LogError(
|
|
|
|
|
"[Dimension] EntityManage.Instance is null during Dimension Awake. Cannot register dimension.",
|
|
|
|
|
this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 5. 处理 defaultOpen 逻辑,设置Program的焦点维度
|
|
|
|
|
// 确保在自身注册到 Program 之后再设置焦点,这样 Program 内部才能找到它
|
|
|
|
|
if (defaultOpen && Program.Instance != null)
|
|
|
|
|
{
|
|
|
|
|
Program.Instance.SetFocusedDimension(_dimensionId);
|
|
|
|
|
// Program 现在会通过 SetFocusedDimension (string) 方法将 FocusedDimension 属性设置为这个 Dimension 实例。
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnDestroy()
|
|
|
|
|
{
|
|
|
|
|
// 当 Dimension 对象被销毁时(例如,场景卸载),从 Program 和 EntityManage 注销
|
|
|
|
|
if (Program.Instance != null) // 检查单例是否仍然存在
|
|
|
|
|
{
|
|
|
|
|
Program.Instance.UnregisterDimension(this);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// 在应用程序退出时,Program.Instance 可能已经为null,这通常是正常的,不打LogError
|
|
|
|
|
Debug.Log(
|
|
|
|
|
"[Dimension] Program.Instance is null during OnDestroy. Skipping unregister for Dimension: " +
|
|
|
|
|
DimensionId, this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (EntityManage.Instance != null) // 检查单例是否仍然存在
|
|
|
|
|
{
|
|
|
|
|
EntityManage.Instance.UnregisterDimension(this);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// 同上,但在清理阶段,这个可能也已为null,只打Log
|
|
|
|
|
Debug.Log(
|
|
|
|
|
"[Dimension] EntityManage.Instance is null during OnDestroy. Skipping unregister for Dimension: " +
|
|
|
|
|
DimensionId, this);
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-08-24 17:15:52 +08:00
|
|
|
|
}
|
2025-08-25 18:24:12 +08:00
|
|
|
|
|
2025-08-24 17:15:52 +08:00
|
|
|
|
}
|