在Unity中,Unity如何神奇地称呼所有“接口”? [英] In Unity, how does Unity magically call all "Interfaces"?

查看:105
本文介绍了在Unity中,Unity如何神奇地称呼所有“接口”?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Unity有一个接口,因为他们称之为 IPointerDownHandler doco )。

Unity has an "interface" as they call it IPointerDownHandler (doco).

您只需实现 OnPointerDown ...

public class Whoa:MonoBehaviour,IPointerDownHandler
    {
    public void OnPointerDown (PointerEventData data)
        { Debug.Log("whoa!"); }
    }

并且Unity将神奇地调用 OnPointerDown 在任何此类MonoBehavior中。

and Unity will "magically" call the OnPointerDown in any such MonoBehavior.

您无需注册,设置活动或执行任何其他操作

你所做的只是将IPointerDownHandler和public void OnPointerDown添加到一个类中,你可以随时神奇地获取这些消息。

All you do is add "IPointerDownHandler" and "public void OnPointerDown" to a class, and you can get those messages at all times magically.

(如果你不是Unity开发者 - 如果你在游戏运行时突然在编辑器中添加一个,它甚至可以工作!)

(If you're not a Unity dev - it even works if you suddenly add one in the Editor while the game is running!)

如何使用扩展程序执行此操作?它更像是一个抽象类 - 他们是如何做到的?所以,我想这样做:

How can I do that with an extension? It's more like an abstract class - how do they do it? So, I want to do this:

public interface IGetNews
 {
 void SomeNews(string s);
 }

然后我可以添加 SomeNews 任何MonoBehavior ,因此可以随时发送新闻。

and then I can add SomeNews to any MonoBehavior, and thus "send news" to those items at any time.

我完全熟悉各种替代解决方案我想知道他们是如何实现这种神奇的行为。

I'm completely familiar with the various alternate solutions. I want to know how they achieve that "magic" behavior.

(顺便说一下:我觉得Unity应该没有调用这些接口,因为,它基本上是没有任何东西像界面一样 - 它恰恰相反!。你可以说它们神奇地创造了一种从多个抽象类继承的方法,我想。)

(BTW: I feel Unity should not have called these interfaces, since, it's basically nothing at all like an interface - it's sort of the opposite!. You could say they magically made a way to inherit from more than one abstract class, I guess.)

除此之外:

为了清楚起见如果您之前没有使用过Unity,执行此操作的常规方法(即,因为我们无法访问Unity魔法)是这样的:只需向您的守护程序添加一个UnityEvent,它将发送有问题的消息:

just for clarity if you've not used Unity before, the conventional way to do this (ie, since we don't have access to Unity magic) is like this: just add a UnityEvent to your daemon which will be sending the message in question:

public class BlahDaemon:MonoBehaviour
  {
  public UnityEvent onBlah;

    ...
    onBlah.Invoke();

假设您有Aaa,Bbb,Ccc等课程,希望获得该消息。如果您是UnityEvent的新手,通常只需将Aaa,Bbb,Ccc中的编辑器拖到BlahDaemon的活动中即可。但是你可以在代码中注册:

Say you have classes Aaa, Bbb, Ccc which want to get the message. If you are new to UnityEvent, often you just "drag in the editor" from Aaa, Bbb, Ccc to the event in BlahDaemon. However you can "register" in code:

public class Aaa:MonoBehaviour
  {
  void Awake()
    {
    BlahDaemon b = Object.FindObjectOfType<BlahDaemon>();
    b.onBlah.AddListener(OnBlah);
    }

  public void OnBlah()
    {
    Debug.Log("almost as good as Unity's");
    }
  }

这与使用Unity的内部几乎一样好魔术虽然在代码中更加混乱。既然你在 Awake 中注册,那么你确实正在使用同样神奇的Unity使用。

This is "almost as good" as using Unity's internal magic, although much more messy in code. Since you are "registering" so to speak in Awake, you are indeed piggybacking on the same magic Unity use.

推荐答案

对于XXXUpdate,OnCollisionXXX和其他MonoBehaviours,Unity注册的方式并不是反射,因为它已被广泛认为是一些内部编译过程。

When it comes to XXXUpdate, OnCollisionXXX and other MonoBehaviours, the way Unity registers is not reflection as it has been widely believed but some internal compilation process.


如何更新已被调用



不,Unity不使用System.Reflection来查找魔术方法每次需要调用一个。

相反,第一次访问给定类型的MonoBehaviour时,底层脚本将通过脚本运行时检查(或者
Mono或IL2CPP)是否定义了任何魔术方法并缓存此
信息。如果MonoBehaviour具有特定方法,则将
添加到正确的列表中,例如,如果脚本具有更新方法
,则将其添加到需要更新的脚本列表中每个
框架。

Instead, the first time a MonoBehaviour of a given type is accessed the underlying script is inspected through scripting runtime (either Mono or IL2CPP) whether it has any magic methods defined and this information is cached. If a MonoBehaviour has a specific method it is added to a proper list, for example if a script has Update method defined it is added to a list of scripts which need to be updated every frame.

在游戏中,Unity只是遍历这些列表并从中执行方法 - 就这么简单。此外,这就是为什么
你的Update方法是公共的还是私有的并不重要。

During the game Unity just iterates through these lists and executes methods from it — that simple. Also, this is why it doesn’t matter if your Update method is public or private.

http://blogs.unity3d.com/2015/12/23/1k-update-calls/

在接口的情况下,我认为它需要更多,因为需要接口。否则,您只需像任何其他MonoBehaviour方法一样添加方法。

In the case of an interface, I would assume it does a bit more since the interface is required. Else, you would just add the method like any other MonoBehaviour methods.

我的假设(可能是错误的),它在这个GameObject上使用了一个基本的GetComponents。然后迭代生成的数组并调用HAS TO BE实现的方法,因为它来自接口。

My assumption (that could be wrong), it uses a basic GetComponents on this GameObject. Then iterate the resulting array and call the method that HAS TO BE implemented since it is from the interface.

您可以使用以下函数重现该模式:

You could reproduce the pattern with:

NewsData data;
if(GetNews(out data))
{
    IGetNews [] getNews = data.gameObject.GetComponents<IGetNews>();
    foreach(IGetNews ign in getNews){ ign.SomeNews(); }
}

GetNews是一种检查是否应该向对象发送一些新闻的方法。您可以将它想象为Physics.Raycast,它将值赋给RaycastHit。如果该对象是出于任何正当理由接收新闻,则填充数据引用。

GetNews is a method that checks if some news should be sent to the object. You could think of it like Physics.Raycast that assigns values to a RaycastHit. Here it fills a data reference if that object is meant to receive news for any valid reasons.

这篇关于在Unity中,Unity如何神奇地称呼所有“接口”?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆