繁体   English   中英

C# Unity:直接调用另一个类的 function 与通过订阅事件调用 function 有什么区别?

[英]C# Unity: What's the difference between calling another class's function directly vs. calling the function by subscribing to an event?

在游戏开发(Unity C#)中,我的脑海中总是有一个关于从另一个 class 调用 function 的最佳方法或最佳方法的问题,我在这里使用了两种方法:

方法一

在 class 1 中公开 function DoSomething并从 class 2 调用它

Class 1:

public class Class1 : MonoBehaviour{

    public static Class1 instance;

    private void Awake()
    {
        instance = this;
    }

    //The function we want to call
    public function DoSomething(){

        Debug.Log("Done something!");

    }

}

Class 2:

public class Class2 : MonoBehaviour{

    private Class1 _class1;

    private void start(){
        _class1 = Class1.instance;
    }

    public function SomeFunction(){

        //Calling the function
        _class1.DoSomething();

    }

}

方法二

Creating an event in class 2 and subscribing to this event in class 1, this way the function will get called when we trigger the event in class 2

Class 1:

public class Class1 : MonoBehaviour{


    private void OnEnable()
    {
        Class2.OnSomeEvent += DoSomething;
    }


    private void OnDisable()
    {
        Class2.OnSomeEvent -= DoSomething;
    }

    //The function we want to call
    private function DoSomething(){

        Debug.Log("Done something!");

    }

}

Class 2:

public class Class2 : MonoBehaviour{

    public static event Action OnSomeEvent = delegate {};

    public function SomeFunction(){

        OnSomeEvent();

    }

}

这两种方法有什么区别,哪一种具有最好的功能和性能?

性能取决于用例。 假设您想在玩家健康低于某个值时在 class 上运行一些方法。 一种选择是检查每个更新是否是时候执行此操作。 然而,那将是低效的。 更好的选择是订阅一个事件,该事件仅在运行状况发生变化时触发,并在那里进行运行状况检查。

除此之外,它还是开发项目架构的额外工具。 您可以使用一个 class 来处理在发生某些X事件时通知其他人并且其他人可以监听该事件,而不是将代码混合在一起。

在您对事件的第二个解决方案中, Class2不需要知道任何关于Class1的信息。 甚至可能还有其他几个对象可能订阅此事件,或者可能没有。 呈现事件的Class2甚至可能属于在订阅者Class1不存在时编写的库。

示例:您正在创建一个控件MySuperButton ,它看起来比标准按钮好得多。 这个按钮将在不同的地方使用并调用不同的点击处理程序。 因此,在编写按钮代码时,您不知道单击按钮时要调用的方法。 你只需提出一个点击事件,你就完成了。

在大多数情况下,性能差异可以忽略不计。

C# 编程指南说:

  • 事件使 class 或 object 在发生感兴趣的事情时通知其他类或对象。
  • 发布者确定何时引发事件; 订阅者决定对事件采取什么行动。

因此,基本上,您可以获得更好的关注点解耦以及依赖关系的反转。

没有任何性能差异。 使用事件系统可以提高代码效率/方便。 假设您希望程序中的某些事情发生在您希望 DoSomething 停止触发的地方,只需取消订阅该事件即可。

Class2.OnSomeEvent -= DoSomething;

另一种情况,假设您的高级开发人员也希望 Class3.SomethingMore 和 Class4.AnotherThing 发生。 除了将它们链接到 DoSomething 方法之外,它们还可以通过多播订阅事件。

 // in Class 3 OnEnable
 Class2.OnSomeEvent += SomethingMore;

 // in Class 4 OnEnable
 Class2.OnSomeEvent += AnotherThing;

现在 OnSomeEvent 将触发所有三个事件。 当您的程序变得更大和复杂时,委托系统使您的代码更具可读性、模块化和更易于调试。 您可以为游戏中的重要事件订阅方法,而不是制作长而难以阅读的方法调用链,这些方法调用链很难返回并进行更改。 通常,Unity 的组件系统被设计为尽可能模块化,委托事件系统也是一种使方法调用模块化的方法。 您还可以说,当其他类订阅事件时,类不需要引用其他类和方法的权限还有一个额外的好处。

再举一个例子,假设您没有使用事件系统,现在您有不同的类定期调用。

Class1.DoSomething();

您的高级开发人员告诉您,无论何时调用 DoSomething(),都需要调用SomethingMore() 和AnotherThing()。 您可以查看代码并尝试找到调用 DoSomething() 的每个位置,并在 SomethingMore() 和 AnotherThing() 之后添加两行,并确保调用的类具有对 Class3 和 Class4 的引用。 另一种选择是在 Class1 中添加对这些类的引用,并在 DoSomething() 方法的末尾添加SomethingMore() 和AnotherThing()。 如果稍后您的团队发现 DoSomething() 应该在某些情况下在没有SomethingMore() 和AnotherThing() 的情况下自行调用时,这个问题就会出现,现在您的代码将开始变得丑陋。

最后,假设您正在实例化“Bug”敌人,当女王命令他们时会 Swarm()。 没有一致数量的“Bug”敌人,因为一些随机生成并被玩家摧毁。 在“错误”脚本中,每个错误订阅女王的“SwarmCommand”事件比在女王脚本中调用“SwarmCommand”来查找对每个错误的引用并调用错误“Swarm”要容易得多()'(您需要调用 FindObjectsWithTag 或保持所有 Bug GameObjects 的最新数组,这将附加一些费用)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM