重构
This commit is contained in:
@@ -1,11 +1,16 @@
|
||||
using UnityEngine;
|
||||
using IndianOceanAssets.Engine2_5D;
|
||||
|
||||
namespace IndianOceanAssets.Engine2_5D
|
||||
{
|
||||
/// <summary>
|
||||
/// 敌人头顶血条 —— 挂在敌人 Prefab 上。
|
||||
/// 血条可视化物体(BG、Fill)已在 Prefab 中预建,
|
||||
/// 运行时直接引用,无需动态创建。
|
||||
/// 血条可视化物体(BG、Fill)已在 Prefab 中预建,运行时直接引用,无需动态创建。
|
||||
///
|
||||
/// 解耦改造:直接引用同物体上的 HealthSystem(RequireComponent 保证存在),
|
||||
/// 订阅其 OnHealthChanged 事件刷新,彻底移除对私有字段的反射读取。
|
||||
/// 注意:不使用"全局共享 IntVariable"承载敌人血量——否则所有敌人血条会显示同一份血量,
|
||||
/// 正确的解法是"每个敌人读自己的 HealthSystem"(同物体组件引用,非 Find / 反射 / 跨对象)。
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(HealthSystem))]
|
||||
public class EnemyHealthBar : MonoBehaviour
|
||||
@@ -33,52 +38,44 @@ namespace IndianOceanAssets.Engine2_5D
|
||||
[Tooltip("满血时是否隐藏血条")]
|
||||
[SerializeField] private bool hideWhenFull = false;
|
||||
|
||||
private HealthSystem _healthSystem;
|
||||
private int _lastHealth = -1;
|
||||
private int _maxHealth;
|
||||
// 同物体上的 HealthSystem(RequireComponent 保证存在;非 Find / 反射 / 跨对象引用)
|
||||
private HealthSystem _healthSource;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_healthSystem = GetComponent<HealthSystem>();
|
||||
if (_healthSystem == null)
|
||||
if (fillRenderer == null || bgRenderer == null)
|
||||
{
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取 maxHealth(通过反射读取私有字段)
|
||||
var field = typeof(HealthSystem).GetField("maxHealth",
|
||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||
if (field != null)
|
||||
_maxHealth = (int)field.GetValue(_healthSystem);
|
||||
_healthSource = GetComponent<HealthSystem>();
|
||||
if (_healthSource != null)
|
||||
{
|
||||
_healthSource.OnHealthChanged += UpdateBar;
|
||||
UpdateBar(_healthSource.CurrentHealth, _healthSource.MaxHealth);
|
||||
}
|
||||
else
|
||||
_maxHealth = 3;
|
||||
|
||||
UpdateBar();
|
||||
{
|
||||
UpdateBar(1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
private void OnDestroy()
|
||||
{
|
||||
UpdateBar();
|
||||
if (_healthSource != null)
|
||||
_healthSource.OnHealthChanged -= UpdateBar;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据当前血量更新血条显示。
|
||||
/// 根据当前血量更新血条显示(事件驱动,无反射、无每帧 LateUpdate)。
|
||||
/// </summary>
|
||||
private void UpdateBar()
|
||||
private void UpdateBar(int currentHealth, int maxHealth)
|
||||
{
|
||||
if (_healthSystem == null || fillRenderer == null || bgRenderer == null) return;
|
||||
if (fillRenderer == null || bgRenderer == null) return;
|
||||
|
||||
// 获取当前血量(反射)
|
||||
var healthField = typeof(HealthSystem).GetField("health",
|
||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||
int currentHealth = healthField != null ? (int)healthField.GetValue(_healthSystem) : _maxHealth;
|
||||
|
||||
// 血量没变化则跳过(性能优化)
|
||||
if (currentHealth == _lastHealth) return;
|
||||
_lastHealth = currentHealth;
|
||||
|
||||
float ratio = Mathf.Clamp01((float)currentHealth / _maxHealth);
|
||||
if (maxHealth <= 0) maxHealth = 1;
|
||||
float ratio = Mathf.Clamp01((float)currentHealth / maxHealth);
|
||||
|
||||
// 更新填充条缩放(居中对齐)
|
||||
fillRenderer.transform.localScale = new Vector3(barWidth * ratio, barHeight, 1f);
|
||||
|
||||
Reference in New Issue
Block a user