Files
SoulliesOfficial 649b7a5ddc 更新
2026-05-23 08:27:50 -04:00

135 lines
4.5 KiB
C#

using System.Collections.Generic;
using Cielonos.MainGame.Characters;
using UnityEngine;
namespace Cielonos.MainGame
{
/// <summary>
/// 索敌评分 Debug 显示组件。
/// 挂载到场景中任意 GameObject 上,运行时在每个敌人头顶显示当前索敌评分。
/// 仅在 Debug 模式开启时绘制,不影响正式构建。
/// </summary>
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<CombatManager.EnemySubmodule.TargetingScore> _cachedScores = new();
private readonly Dictionary<CharacterBase, CombatManager.EnemySubmodule.TargetingScore> _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);
}
}
}
}