using System.Collections.Generic; using Cielonos.MainGame.Characters; using UnityEngine; namespace Cielonos.MainGame { /// /// 索敌评分 Debug 显示组件。 /// 挂载到场景中任意 GameObject 上,运行时在每个敌人头顶显示当前索敌评分。 /// 仅在 Debug 模式开启时绘制,不影响正式构建。 /// public class TargetingDebugDisplay : MonoBehaviour { [Header("Debug 设置")] [Tooltip("是否启用索敌评分显示")] public bool enableDebug; [Tooltip("索敌评分查询半径")] public float debugRadius = 20f; [Tooltip("文字显示在敌人头顶的偏移量")] public float headOffset = 2.2f; [Tooltip("文字大小")] public int fontSize = 20; [Tooltip("最高分目标的标记颜色")] public Color bestTargetColor = Color.green; [Tooltip("普通目标的文字颜色")] public Color normalColor = Color.white; [Tooltip("背景颜色")] public Color backgroundColor = new Color(0f, 0f, 0f, 0.6f); private List _cachedScores = new(); private readonly Dictionary _scoreMap = new(); private float _updateInterval = 0.1f; private float _nextUpdateTime; private GUIStyle _labelStyle; private GUIStyle _bgStyle; private Texture2D _bgTexture; private void Update() { if (!enableDebug) return; if (Time.time >= _nextUpdateTime) { _nextUpdateTime = Time.time + _updateInterval; _cachedScores = CombatManager.EnemySm.GetScoredEnemies(debugRadius); _scoreMap.Clear(); foreach (var score in _cachedScores) { _scoreMap[score.target] = score; } } } private void OnGUI() { if (!enableDebug || _cachedScores.Count == 0) return; EnsureStyles(); Camera cam = Camera.main; if (cam == null) return; bool isFirst = true; foreach (var score in _cachedScores) { if (score.target == null) continue; Vector3 worldPos = score.target.centerPoint.position + Vector3.up * headOffset; Vector3 screenPos = cam.WorldToScreenPoint(worldPos); if (screenPos.z <= 0) continue; float guiY = Screen.height - screenPos.y; string text = $"Total: {score.totalScore:F2}"; if (score.bonusScore != 0f) { text += $" (Base: {score.baseScore:F2} + Bonus: {score.bonusScore:F2})"; } text += $"\nDist: {score.distanceScore:F2} Input: {score.inputDirScore:F2}" + $"\nCam: {score.cameraFacingScore:F2} Sticky: {score.stickyScore:F2} Lock: {score.lockOnScore:F2}"; GUIContent content = new GUIContent(text); Vector2 size = _labelStyle.CalcSize(content); // CalcSize 不考虑换行,用 CalcHeight 代替 float height = _labelStyle.CalcHeight(content, size.x); Rect bgRect = new Rect(screenPos.x - size.x / 2 - 4, guiY - height - 4, size.x + 8, height + 8); Rect textRect = new Rect(screenPos.x - size.x / 2, guiY - height, size.x, height); GUI.Box(bgRect, GUIContent.none, _bgStyle); _labelStyle.normal.textColor = isFirst ? bestTargetColor : normalColor; GUI.Label(textRect, content, _labelStyle); isFirst = false; } } private void EnsureStyles() { if (_labelStyle != null) return; _bgTexture = new Texture2D(1, 1); _bgTexture.SetPixel(0, 0, backgroundColor); _bgTexture.Apply(); _bgStyle = new GUIStyle(GUI.skin.box) { normal = { background = _bgTexture } }; _labelStyle = new GUIStyle(GUI.skin.label) { fontSize = fontSize, alignment = TextAnchor.UpperCenter, wordWrap = false }; } private void OnDestroy() { if (_bgTexture != null) { Destroy(_bgTexture); } } } }