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:
138
Assets/_Game/Scripts/World/Map/MapProgressDisplay.cs
Normal file
138
Assets/_Game/Scripts/World/Map/MapProgressDisplay.cs
Normal file
@@ -0,0 +1,138 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
using TMPro;
|
||||
using System.Collections.Generic;
|
||||
using BaseGames.Core;
|
||||
using BaseGames.Core.Events;
|
||||
|
||||
namespace BaseGames.World.Map
|
||||
{
|
||||
/// <summary>
|
||||
/// 探索进度百分比 UI 组件。
|
||||
/// 显示全局探索进度和当前区域探索进度,随 OnExplorationChanged 实时更新。
|
||||
/// <para>挂在 HUD 或地图面板下;需配置两个 TMP_Text 字段和可选的 StringEventChannelSO。</para>
|
||||
/// </summary>
|
||||
public class MapProgressDisplay : MonoBehaviour
|
||||
{
|
||||
[Header("文本组件")]
|
||||
[Tooltip("全局探索进度文本,例如 '已探索 42%'。留空则不更新。")]
|
||||
[SerializeField] private TMP_Text _globalProgressText;
|
||||
|
||||
[Tooltip("当前区域进度文本,例如 '区域:67%'。留空则不更新。")]
|
||||
[SerializeField] private TMP_Text _regionProgressText;
|
||||
|
||||
[Header("格式字符串({0:P0} = 百分比,{1} = 区域显示名)")]
|
||||
[SerializeField] private string _globalFormat = "已探索 {0:P0}";
|
||||
[SerializeField] private string _regionFormat = "{1}:{0:P0}";
|
||||
|
||||
[Header("区域名映射(与 RegionNameDisplay 共用同一机制)")]
|
||||
[Tooltip("RegionId → 本地化显示名映射。未配置时直接显示 RegionId。")]
|
||||
[FormerlySerializedAs("_regionNameEntries")]
|
||||
[SerializeField] private RegionNameEntry[] _regionNames;
|
||||
|
||||
[Header("Event Channels")]
|
||||
[Tooltip("区域切换事件;订阅后区域切换时自动刷新区域进度。")]
|
||||
[SerializeField] private StringEventChannelSO _onRegionChanged;
|
||||
|
||||
private IMapService _mapSvc;
|
||||
private string _currentRegionId;
|
||||
private readonly CompositeDisposable _subs = new();
|
||||
// R15-N2 RegionId → Entry 字典,将 ResolveRegionDisplayName 从 O(N) 降至 O(1)
|
||||
private Dictionary<string, RegionNameEntry> _regionDict;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
BuildRegionDict();
|
||||
}
|
||||
|
||||
private void OnValidate() => BuildRegionDict();
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
_mapSvc = ServiceLocator.GetOrDefault<IMapService>();
|
||||
if (_mapSvc != null)
|
||||
{
|
||||
_mapSvc.OnExplorationChanged += Refresh;
|
||||
_currentRegionId = _mapSvc.CurrentRegionId;
|
||||
}
|
||||
_onRegionChanged?.Subscribe(OnRegionChanged).AddTo(_subs);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
if (_mapSvc != null)
|
||||
{
|
||||
_mapSvc.OnExplorationChanged -= Refresh;
|
||||
_mapSvc = null;
|
||||
}
|
||||
_subs.Clear();
|
||||
}
|
||||
|
||||
private void OnRegionChanged(string regionId)
|
||||
{
|
||||
_currentRegionId = regionId;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
/// <summary>立即刷新进度文本。可由外部调用(例如地图面板打开时)。</summary>
|
||||
public void Refresh()
|
||||
{
|
||||
if (_mapSvc == null)
|
||||
_mapSvc = ServiceLocator.GetOrDefault<IMapService>();
|
||||
if (_mapSvc == null) return;
|
||||
|
||||
// 全局探索进度
|
||||
if (_globalProgressText != null)
|
||||
{
|
||||
float progress = _mapSvc.GetExplorationProgress();
|
||||
try
|
||||
{
|
||||
_globalProgressText.text = string.Format(_globalFormat, progress);
|
||||
}
|
||||
catch (System.FormatException)
|
||||
{
|
||||
_globalProgressText.text = $"{progress:P0}";
|
||||
Debug.LogWarning($"[MapProgressDisplay] _globalFormat 格式字符串配置有误:'{_globalFormat}',已回退到默认显示。", this);
|
||||
}
|
||||
}
|
||||
|
||||
// 当前区域进度
|
||||
if (_regionProgressText != null && !string.IsNullOrEmpty(_currentRegionId))
|
||||
{
|
||||
var rooms = _mapSvc.GetRoomsByRegion(_currentRegionId);
|
||||
if (rooms != null && rooms.Length > 0)
|
||||
{
|
||||
int exploredCount = 0;
|
||||
foreach (var r in rooms)
|
||||
if (r != null && _mapSvc.IsExplored(r.RoomId)) exploredCount++;
|
||||
float regionProgress = (float)exploredCount / rooms.Length;
|
||||
// R15-N2 解析区域显示名(本地化 Key → DisplayName → RegionId 回退)
|
||||
string regionDisplayName = ResolveRegionDisplayName(_currentRegionId);
|
||||
try
|
||||
{
|
||||
_regionProgressText.text = string.Format(_regionFormat, regionProgress, regionDisplayName);
|
||||
}
|
||||
catch (System.FormatException)
|
||||
{
|
||||
_regionProgressText.text = $"{regionDisplayName}:{regionProgress:P0}";
|
||||
Debug.LogWarning($"[MapProgressDisplay] _regionFormat 格式字符串配置有误:'{_regionFormat}',已回退到默认显示。", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── 辅助方法 ──────────────────────────────────────────────────────────
|
||||
|
||||
/// <summary>预建 RegionId → Entry 字典,O(1) 查询。</summary>
|
||||
private void BuildRegionDict()
|
||||
=> _regionDict = MapServiceExtensions.BuildRegionDict(_regionNames);
|
||||
|
||||
/// <summary>
|
||||
/// 将 regionId 解析为玩家可读的显示名。
|
||||
/// 优先读 LocKey(本地化),其次 DisplayName,最后回退到 regionId 本身。
|
||||
/// </summary>
|
||||
private string ResolveRegionDisplayName(string regionId)
|
||||
=> MapServiceExtensions.ResolveRegionDisplayName(_regionDict, regionId);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user