v10 全量评审:修复 TD-06 至 TD-12(InputReader 移除资产扫描回退 / EmergencySave 解除 LocalFileStorage 直接依赖 / AccessibilityManager 注册 IAccessibilityService / HUDController HP/SpringIcon SetActive 复用 / MovingPlatform 缓存 WaitForSeconds / RewardSO IRewardTarget 解耦 Quest←Player 依赖 / CrashReporter 频率限制崩溃日志)

This commit is contained in:
2026-05-12 16:18:46 +08:00
parent ebbbb7332e
commit 9284278578
27 changed files with 1697 additions and 125 deletions

View File

@@ -18,14 +18,20 @@ namespace BaseGames.UI
[SerializeField] private float _floatDistance = 1.5f;
[SerializeField] private float _duration = 0.8f;
private UnityEngine.Camera _cam;
/// <summary>
/// 父级 Canvas用于 RectTransformUtility 坐标转换)。
/// 适配所有 Canvas 渲染模式Overlay / Camera / World Space
/// Screen Space - Overlay 时可传 null会自动 fallback 到 null camera
/// </summary>
[SerializeField] private Canvas _parentCanvas;
private RectTransform _rectTransform;
private Coroutine _animCoroutine;
private void Awake()
{
_rectTransform = (RectTransform)transform;
_cam = UnityEngine.Camera.main;
// 不在 Awake 缓存 Camera.main避免 Boss 过场切换主摄像机后引用过期
}
/// <summary>
@@ -39,16 +45,36 @@ namespace BaseGames.UI
_text.text = damage.ToString();
_text.color = GetColorForType(type);
// 将世界坐标转为屏幕坐标
if (_cam != null)
{
Vector2 screenPos = _cam.WorldToScreenPoint(worldPosition);
_rectTransform.anchoredPosition = screenPos;
}
SetAnchoredPosition(worldPosition);
_animCoroutine = StartCoroutine(FloatAndFade(worldPosition));
}
private void SetAnchoredPosition(Vector2 worldPosition)
{
var cam = (_parentCanvas != null && _parentCanvas.renderMode == RenderMode.ScreenSpaceCamera)
? _parentCanvas.worldCamera
: UnityEngine.Camera.main;
var screenPoint = UnityEngine.Camera.main != null
? (Vector2)UnityEngine.Camera.main.WorldToScreenPoint(worldPosition)
: Vector2.zero;
var canvasRect = _parentCanvas != null
? (RectTransform)_parentCanvas.transform
: null;
if (canvasRect != null)
{
RectTransformUtility.ScreenPointToLocalPointInRectangle(
canvasRect, screenPoint, cam, out var localPoint);
_rectTransform.anchoredPosition = localPoint;
}
else
{
_rectTransform.anchoredPosition = screenPoint;
}
}
private IEnumerator FloatAndFade(Vector2 startWorld)
{
float elapsed = 0f;
@@ -59,10 +85,7 @@ namespace BaseGames.UI
{
float t = elapsed / _duration;
// 向上飘动(屏幕坐标)
Vector2 currentWorld = startWorld + new Vector2(0, _floatDistance * t);
if (_cam != null)
_rectTransform.anchoredPosition = (Vector2)_cam.WorldToScreenPoint(currentWorld);
SetAnchoredPosition(startWorld + new Vector2(0, _floatDistance * t));
// alpha 淡出(后半段开始)
_text.color = new Color(color.r, color.g, color.b,

View File

@@ -66,12 +66,17 @@ namespace BaseGames.UI.HUD
private void RebuildHPCells(int max)
{
foreach (var cell in _hpCells)
if (cell != null) Destroy(cell);
_hpCells.Clear();
if (_hpContainer == null || _hpCellPrefab == null) return;
// 复用现有 Cell仅在数量不足时 Instantiate 补充,超出时 SetActive(false) 而非 Destroy
for (int i = 0; i < max; i++)
_hpCells.Add(Instantiate(_hpCellPrefab, _hpContainer));
{
if (i < _hpCells.Count)
_hpCells[i].SetActive(true);
else
_hpCells.Add(Instantiate(_hpCellPrefab, _hpContainer));
}
for (int i = max; i < _hpCells.Count; i++)
if (_hpCells[i] != null) _hpCells[i].SetActive(false);
}
private void UpdateSoul(int val)
@@ -91,12 +96,17 @@ namespace BaseGames.UI.HUD
private void RebuildSpringIcons(int charges)
{
foreach (var icon in _springIcons)
if (icon != null) Destroy(icon);
_springIcons.Clear();
if (_springContainer == null || _springIconPrefab == null) return;
// 复用已有图标,超出数量时 SetActive(false)
for (int i = 0; i < charges; i++)
_springIcons.Add(Instantiate(_springIconPrefab, _springContainer));
{
if (i < _springIcons.Count)
_springIcons[i].SetActive(true);
else
_springIcons.Add(Instantiate(_springIconPrefab, _springContainer));
}
for (int i = charges; i < _springIcons.Count; i++)
if (_springIcons[i] != null) _springIcons[i].SetActive(false);
}
private void UpdateFormIcon(int formIndex)