在 Unity 中,Unity 是如何神奇地调用所有“接口"的? [英] In Unity, how does Unity magically call all "Interfaces"?

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

问题描述

Unity 有一个接口":

Unity has an "interface":

IPointerDownHandler (doco)

您只需实现 OnPointerDown ...

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

和 Unity 将神奇地"在任何此类 MonoBehavior 中调用 OnPointerDown.

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

您无需注册它们、设置活动或执行任何其他操作.

您在语法上所做的就是添加IPointerDownHandler";和public void OnPointerDown"到一个班级,你可以神奇地收到这些消息.

All you do syntactically is add "IPointerDownHandler" and "public void OnPointerDown" to a class, and you can get those messages 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!)

所以,我想这样做:

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

然后我可以将 SomeNews 添加到任何 MonoBehavior.

(顺便说一句:我觉得他们不应该称这些为接口",因为它基本上完全不像一个接口——它有点相反!你可以说他们神奇地制作了一个一种从多个抽象类继承的方法,我猜.)

(BTW: I feel they 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 添加到您的守护进程,它将发送有问题的消息:

if you've not used Unity before, the conventional way to do this - since we don't have access to Unity magic - is 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.只需连接Unity事件(在编辑器中或在代码中拖动),示例:

Say you have classes Aaa, Bbb, Ccc which want to get the message. Simply connect the Unity event (either by dragging in the editor or in code), example:

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");
    }
  }

您基本上是在注册"你在 Awake 中的调用,你确实是在利用 Unity 的神奇用法——不管它是什么.但我想直接使用魔法.

You're basically "registering" your call in Awake, you are indeed piggybacking on the magic Unity use - whatever it is. But I want to use the magic directly.

推荐答案

当谈到 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 有一个特定的方法,它是添加到适当的列表中,例如,如果脚本具有 Update 方法定义它被添加到需要更新的脚本列表中每一帧.

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-更新调用/

在接口的情况下,我认为它会做更多的事情,因为需要接口.否则,您只需像任何其他 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.

我的假设(这可能是错误的),它在这个游戏对象上使用了一个基本的 GetComponents.然后迭代结果数组并调用必须实现的方法,因为它来自接口.

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天全站免登陆