血条脚本里写 GameObject.Find("Player"),场景里玩家一改名,运行时就空了。Find 还会扫层级,热路径里用更不合适。后来血量变化改成事件:玩法只负责改数据并广播,UI 自己听。
public static class PlayerSignals
{
public static event Action<int, int> HealthChanged;
public static void RaiseHealth(int current, int max)
{
HealthChanged?.Invoke(current, max);
}
}
public class HealthBarView : MonoBehaviour
{
void OnEnable() => PlayerSignals.HealthChanged += Refresh;
void OnDisable() => PlayerSignals.HealthChanged -= Refresh;
void Refresh(int current, int max)
{
_fill.fillAmount = (float)current / max;
}
}
三种我常用的强度
- 同物体内部:直接序列化引用或
GetComponent。 - 跨系统、同场景:静态事件或轻量 EventBus,注意退订。
- 想在 Inspector 里接线、又不想两个预制体互相拖死:用 ScriptableObject 当事件通道。
单例管理器不是不能用,但“所有系统都去问同一个 Manager”很快会变成上帝对象。能通知的就通知,能配置的就配置,少在运行时满世界找物体。
备忘:静态事件在域重载或退出 Play 后如果没退订,编辑器里会留下幽灵回调。养成 Enable / Disable 配对的习惯最省事。