我如何制作可以在没有事件的情况下订阅的某些功能(就像 Unity 那样)?

How do I make certain functions that can be subscribed to without events (like Unity does)?

在 Unity 中,当您创建一个新的 MonoBehaviour class 时,它会附带一整套您可以轻松挂接的函数 - 例如 Update()FixedUpdate()Awake()。我正在制作我自己的组件实体系统,我正在尝试添加一系列可以很容易地被我创建的组件挂钩的功能。我已经将我的基础 class 抽象化,并将 UpdateDraw 作为可以继承的抽象函数。这工作正常,除了 all 我的组件必须实现所有这些功能;像 Initialize 这样的东西对某些组件有用但对其他组件没有用,我不确定如何模拟这种行为。

反射完成了吗?

您可以将方法定义为 virtualoverride,而不是将它们定义为 abstract ] 只在必要时使用它们。

class BaseComponent : MonoBehaviour
{
    public virtual void OnAwesomeEvent()
    {
        // do nothing or implement default behaviour
    }
}

class ShinyComponent : BaseComponent
{
    public override void OnAwesomeEvent()
    {
        Debug.Log("I've been waiting for this!");

        // If you need the default implementation you can call it with
        // base.OnAwesomeEvent()
    }
}

class LazyComponent : BaseComponent
{
    // I do nothing and no one cares
}

免责声明:

I'm making my own component-entity system and I'm trying to add a range of functions that can easily be hooked onto by the components I create.

我不是特别喜欢 Unity 在这方面的 "magic methods" 方法。我认为实施 interfacesoverriding virtual functions 通常是一种更清洁的解决方案。 我曾经使用过 Unity 的方法,用于一个 AI 插件,它应该调用用户定义的方法而不强制扩展 class(主要是因为我必须避免在修改 AI 的行为时重新编译代码)

无论如何,为了实现什么:

1) 发送消息

SendMessage使用纯反射实现:只有调用SendMessage时才能知道目标方法名。 这看起来很方便(也许是,我仍然从未使用过,也觉得没有必要),但有几个缺点:

  1. 性能:反射是昂贵的(检查一些基准,它最终比直接方法调用慢数百倍)
  2. 类型不安全: 无法在编译时检查传递的参数类型是否正确。

2) MonoBehaviour 消息

这些方法(如AwakeUpdateOnCollision、...)略有不同,因为Unity 可以知道签名并编译委托。 (我不确定实现方式,但我做过类似的事情)。

article 中详细描述了实现类似内容的方法。 基本上你只在初始化中使用反射,但是一旦获得 MethodInfo,你可以使用 Delegate.CreateDelegate.

将方法编译为委托

结果:

  • 你仍然使用反射,但只在初始化时使用
  • 编译后,委托几乎与标准方法调用(或事件)一样快。