Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我如何制作某些无需事件即可订阅的函数(如Unity)?_C#_Inheritance_Unity3d_Abstract Class - Fatal编程技术网

C# 我如何制作某些无需事件即可订阅的函数(如Unity)?

C# 我如何制作某些无需事件即可订阅的函数(如Unity)?,c#,inheritance,unity3d,abstract-class,C#,Inheritance,Unity3d,Abstract Class,在Unity中,当您创建一个新的monobhavior类时,它附带了一整套可以轻松挂接的函数,例如Update()、FixedUpdate()和Awake()。我正在创建自己的组件实体系统,并且我正在尝试添加一系列功能,这些功能可以很容易地由我创建的组件连接。我将基类抽象化,并将Update和Draw作为抽象函数,然后可以继承它们。这很好,除了我的所有组件都必须实现所有这些功能之外;像初始化这样的东西对某些组件很有用,但对其他组件则没有,我不知道如何模拟这种行为 它是通过反射完成的吗?您可以将方

在Unity中,当您创建一个新的
monobhavior
类时,它附带了一整套可以轻松挂接的函数,例如
Update()
FixedUpdate()
Awake()
。我正在创建自己的组件实体系统,并且我正在尝试添加一系列功能,这些功能可以很容易地由我创建的组件连接。我将基类抽象化,并将
Update
Draw
作为抽象函数,然后可以继承它们。这很好,除了我的所有组件都必须实现所有这些功能之外;像初始化这样的东西对某些组件很有用,但对其他组件则没有,我不知道如何模拟这种行为


它是通过反射完成的吗?

您可以将方法定义为虚拟方法,而不是将其定义为抽象方法,并仅在必要时重写它们

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
}

您可以将方法定义为虚拟方法,而不是将其定义为抽象方法,并仅在必要时重写它们

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轻松连接的功能范围 创造

我并不特别喜欢unity在这方面的“神奇方法”。我认为实现
接口
覆盖虚拟函数
通常是一个更干净的解决方案。 我曾经使用过Unity的方法,对于一个AI插件,它应该调用用户定义的方法,而不必强制扩展类(基本上是因为我必须避免在修改AI行为时重新编译代码)

在任何情况下,对于与实施有关的内容:

1)发送消息

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

  • 性能:反射代价高昂(检查一些基准测试,它最终比直接方法调用慢数百倍)
  • 非类型安全:无法在编译时检查传递的参数是否为正确的类型
  • 2)单一行为信息

    这些方法(如
    唤醒
    更新
    碰撞
    ,…)略有不同,因为Unity可以知道签名并编译代理。(我不确定实现情况,但我做过类似的事情)

    本文很好地描述了实现类似功能的方法。 基本上,您只在初始化中使用反射,但一旦获得
    MethodInfo
    ,就可以使用
    delegate.CreateDelegate
    将方法编译为委托

    结果:

    • 您仍然使用反射,但仅在初始化中使用
    • 一旦编译,委托几乎与标准方法调用(或事件)一样快
    免责声明:

    我正在创建自己的组件实体系统,并尝试添加一个 可由组件I轻松连接的功能范围 创造

    我并不特别喜欢unity在这方面的“神奇方法”。我认为实现
    接口
    覆盖虚拟函数
    通常是一个更干净的解决方案。 我曾经使用过Unity的方法,对于一个AI插件,它应该调用用户定义的方法,而不必强制扩展类(基本上是因为我必须避免在修改AI行为时重新编译代码)

    在任何情况下,对于与实施有关的内容:

    1)发送消息

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

  • 性能:反射代价高昂(检查一些基准测试,它最终比直接方法调用慢数百倍)
  • 非类型安全:无法在编译时检查传递的参数是否为正确的类型
  • 2)单一行为信息

    这些方法(如
    唤醒
    更新
    碰撞
    ,…)略有不同,因为Unity可以知道签名并编译代理。(我不确定实现情况,但我做过类似的事情)

    本文很好地描述了实现类似功能的方法。 基本上,您只在初始化中使用反射,但一旦获得
    MethodInfo
    ,就可以使用
    delegate.CreateDelegate
    将方法编译为委托

    结果:

    • 您仍然使用反射,但仅在初始化中使用
    • 一旦编译,委托几乎与标准方法调用(或事件)一样快

    我想你可以使用反射来实现这一点,但对于一个更简单的开箱即用的解决方案,你可以看看“SendMessage”:我想你可以使用反射来实现这一点,但是对于一个更简单的开箱即用的解决方案,你可以看看“SendMessage”:我已经忘记了!愚蠢的谢谢你!我忘了!愚蠢的谢谢你!谢谢,这是一本非常有用的指南:)谢谢,这是一本非常有用的指南:)