Add independent review reports for Minimap system (Rounds 8, 9, and 26)
- Round 8 report highlights improvements in architecture, editor usability, and data robustness, with a total score of 80/100. - Round 9 report focuses on editor extension capabilities, identifying issues with room data indexing and layout editing, resulting in a score of 76/100. - Round 26 report evaluates the system against commercial standards, noting new issues and confirming previous fixes, with a score of 95.8/100.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
// NOTE: 此文件包含 MapPinManager 类,但文件名为 MapPin.cs(历史遗留,Unity .meta 绑定限制不可安全重命名)。
|
||||
// 如需搜索,请搜索 "MapPinManager" 类名,而非文件名。
|
||||
// PinSpriteEntry 已迁移到 MapPinConfigSO.cs(R12-N3)。
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using BaseGames.Core;
|
||||
@@ -7,14 +8,6 @@ using BaseGames.Core.Save;
|
||||
|
||||
namespace BaseGames.World.Map
|
||||
{
|
||||
/// <summary>标记类型与显示精灵的映射表项(从 MapPanel 移入,与数据同文件管理)。</summary>
|
||||
[System.Serializable]
|
||||
public class PinSpriteEntry
|
||||
{
|
||||
public PinType PinType;
|
||||
public Sprite Sprite;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 地图自定义标记管理器(架构 15_MapShopModule §1.5)。
|
||||
/// 实现 <see cref="ISaveable"/> 和 <see cref="IPinService"/>,通过 ServiceLocator 对外暴露。
|
||||
@@ -24,6 +17,7 @@ namespace BaseGames.World.Map
|
||||
/// </para>
|
||||
/// MapPin/PinType 数据类定义在 SaveData.cs(BaseGames.Core.Save)中,避免循环依赖。
|
||||
/// </summary>
|
||||
[DefaultExecutionOrder(-500)] // 晚于 MapPlayerTracker(-600),早于默认 0,确保 IPinService 在 UI SubscribeServices 前已注册
|
||||
public class MapPinManager : MonoBehaviour, ISaveable, IPinService
|
||||
{
|
||||
private List<MapPin> _pins = new();
|
||||
@@ -33,15 +27,44 @@ namespace BaseGames.World.Map
|
||||
/// <summary>每次 Pin 集合发生变化时自增;外部消费方通过此版本号实现脏检查。</summary>
|
||||
public int PinsVersion { get; private set; }
|
||||
|
||||
private IMapService _mapSvc; // Start 中缓存,避免 CreatePin 每次调用 ServiceLocator
|
||||
|
||||
private bool _isDuplicate;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (ServiceLocator.GetOrDefault<IPinService>() != null)
|
||||
{
|
||||
_isDuplicate = true;
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
// 服务注册迁移到 Awake/OnDestroy(与 MapManager / MapPlayerTracker 对齐)
|
||||
// 避免 OnEnable/OnDisable 模式下反复 Register/Unregister 导致其他模块持有过期引用
|
||||
ServiceLocator.Register<IPinService>(this);
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (_isDuplicate) return;
|
||||
_mapSvc = ServiceLocator.GetOrDefault<IMapService>();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
if (_isDuplicate) return;
|
||||
ServiceLocator.GetOrDefault<ISaveableRegistry>()?.Register(this);
|
||||
ServiceLocator.Register<IPinService>(this);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
if (_isDuplicate) return;
|
||||
ServiceLocator.GetOrDefault<ISaveableRegistry>()?.Unregister(this);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (_isDuplicate) return;
|
||||
ServiceLocator.Unregister<IPinService>(this);
|
||||
}
|
||||
|
||||
@@ -57,15 +80,34 @@ namespace BaseGames.World.Map
|
||||
if (_pins.Remove(pin)) PinsVersion++;
|
||||
}
|
||||
|
||||
/// <summary>便捷方法:用枚举类型创建并添加标记。</summary>
|
||||
/// <summary>
|
||||
/// 便捷方法:用枚举类型创建并添加标记。
|
||||
/// <para>
|
||||
/// 参数会做安全校验:roomId 为空时返回 null;normX/normY 自动 Clamp01;
|
||||
/// note 限制 64 字符;可选检查 roomId 是否存在于数据库(不存在时 Warning,但仍允许创建以兼容运行时尚未加载的数据库场景)。
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public MapPin CreatePin(string roomId, float normX, float normY,
|
||||
PinType type = PinType.Marker, string note = "")
|
||||
{
|
||||
if (string.IsNullOrEmpty(roomId))
|
||||
{
|
||||
Debug.LogWarning("[MapPinManager] CreatePin 失败:roomId 为空。");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 可选 RoomId 存在性验证:数据库已就绪时检查,未就绪时跳过(不阻塞)
|
||||
if (_mapSvc?.Database != null && _mapSvc.Database.GetRoom(roomId) == null)
|
||||
Debug.LogWarning($"[MapPinManager] CreatePin: roomId '{roomId}' 在数据库中不存在,标记将不会渲染。");
|
||||
|
||||
if (!string.IsNullOrEmpty(note) && note.Length > 64)
|
||||
note = note.Substring(0, 64);
|
||||
|
||||
var pin = new MapPin
|
||||
{
|
||||
RoomId = roomId,
|
||||
NormalizedPosX = normX,
|
||||
NormalizedPosY = normY,
|
||||
NormalizedPosX = Mathf.Clamp01(normX),
|
||||
NormalizedPosY = Mathf.Clamp01(normY),
|
||||
PinTypeInt = (int)type,
|
||||
Note = note,
|
||||
};
|
||||
@@ -75,11 +117,14 @@ namespace BaseGames.World.Map
|
||||
|
||||
// ── ISaveable ─────────────────────────────────────────────────────────
|
||||
|
||||
public void OnSave(SaveData data) => data.Map.Pins = _pins;
|
||||
// 拷贝 List 而非直接共享引用,避免序列化期间 AddPin/RemovePin 修改集合产生并发问题
|
||||
public void OnSave(SaveData data) => data.Map.Pins = new List<MapPin>(_pins);
|
||||
|
||||
public void OnLoad(SaveData data)
|
||||
{
|
||||
_pins = data.Map.Pins ?? new List<MapPin>();
|
||||
// R11-N3 防御性拷贝:避免与 SaveData.Map.Pins 共享同一引用,
|
||||
// 防止调用方后续修改 data 时污染 _pins(与 OnSave 的方向对称)
|
||||
_pins = data.Map.Pins != null ? new List<MapPin>(data.Map.Pins) : new List<MapPin>();
|
||||
PinsVersion++; // 加载存档后通知消费方重绘
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user