Unity Action的解耦类

编程语言 2026-07-11

我在学习Unity,想知道如何避免依赖。我有这两个类,其中一个会生成一个事件:

public class ClickController : MonoBehaviour
{
    public static event Action<ClickController> OnClickControllerEvent; // new

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
            OnLeftClick();
    }

    private void OnLeftClick()
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;

        if (Physics.Raycast(ray, out hit))
        {
            Debug.Log("The cube was clicked! Notifying subscribers!");

            if (OnClickControllerEvent != null) // new
                OnClickControllerEvent(this);
        }
    }
}

另一个类用于监听该事件:

public class HealthController : MonoBehaviour
{
    [SerializeField] private int minHealth = 0;
    [SerializeField] private int maxHealth = 100;

    private int health = 100;

    private void OnEnable() // new
    {
        ClickController.OnClickControllerEvent += TakeDamage;
    }

    private void OnDisable() // new
    {
        ClickController.OnClickControllerEvent -= TakeDamage;
    }

    private void TakeDamage(ClickController clickController) // changed
    {
        health -= 10;

        if (health <= 0)
            Debug.Log("I'm dead now! :(");
    }
}

在这个示例中,类 HealthController 需要知道类 ClickController

ClickController.OnClickControllerEvent += TakeDamage;

为了避免这种情况,我尝试使用一个接口:

using System;

interface IClickInterface
{
    public static event Action OnClickControllerEvent;
}

但接口不支持静态成员。

HealthController 类知道 ClickController 类可以吗?

或者,还有其他实现方式吗?

解决方案

如果你使用的是静态事件,其实很难再有较高的抽象层。

静态事件也是一种全局变量,因此可变全局状态的所有缺点同样适用于静态事件。因此,只有在你绝对确定只会存在一个这样的事件时,才推荐使用这种做法。

标准做法是避免使用静态变量,而改用依赖注入,即类似如下的做法:

interface IClickInterface
{
    event Action OnClickControllerEvent;
}
public class ClickController : MonoBehaviour, IClickInterface
{
    public event Action OnClickControllerEvent; 
    private void OnLeftClick()
    {
        ...
        OnClickControllerEvent?.Invoke()
    }
}

public class HealthController(IClickInterface clickController) : MonoBehaviour
{
    ...
    private void OnEnable()  => clickController.OnClickControllerEvent += TakeDamage;
    private void OnDisable()  => clickController.OnClickControllerEvent -= TakeDamage;
}

这种做法允许在需要时将 ClickController 替换为其他类。

你也可以考虑使用依赖注入容器来简化所有对象的创建。有几种替代方案,下面是一些示例:

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章