Unity有一个"界面":
IPointerDownHandler
(doco)
您只需实施OnPointerDown ...
public class Whoa:MonoBehaviour,IPointerDownHandler
{
public void OnPointerDown (PointerEventData data)
{ Debug.Log("whoa!"); }
}
和Unity将会神奇地"在任何此类MonoBehavior中调用OnPointerDown
。
您不必注册,设置活动,也不需要做任何其他事情。
你在语法上做的就是添加" IPointerDownHandler"和#34; public void OnPointerDown"到了一个班级,你可以神奇地获得这些信息。
(如果您不是Unity开发者 - 如果您在游戏运行时突然在编辑器中添加一个,它甚至会起作用!)
所以,我想这样做:
public interface IGetNews
{
void SomeNews(string s);
}
然后我可以将SomeNews
添加到任何MonoBehavior 。
(顺便说一句:我觉得他们不应该把这些称为"接口",因为它基本上没有任何东西像接口一样 - 它恰恰相反!你可以说他们神奇地想要从一个以上的抽象类继承,我想。)
除了:
如果您之前没有使用过Unity,那么传统的方法就是这样做 - 因为我们无法访问Unity魔法 - 只需向您的守护程序添加一个UnityEvent,它将发送有问题的消息:
public class BlahDaemon:MonoBehaviour
{
public UnityEvent onBlah;
...
onBlah.Invoke();
假设您有Aaa,Bbb,Ccc等课程,希望得到这些消息。只需连接Unity事件(通过在编辑器或代码中拖动),例如:
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");
}
}
你基本上&#34;注册&#34;你在Awake
的召唤,你确实在捎带神奇的Unity使用 - 无论它是什么。但我想直接使用魔法。
答案 0 :(得分:26)
对于XXXUpdate,OnCollisionXXX和其他MonoBehaviours,Unity注册的方式并不是反射,因为它被广泛认为是一些内部编译过程。
如何更新
不,Unity每次需要调用时都不会使用System.Reflection查找魔术方法。
相反,第一次访问给定类型的MonoBehaviour时,将通过脚本运行时检查底层脚本(或者 Mono或IL2CPP)是否有任何魔法方法定义和此 信息被缓存。如果MonoBehaviour有特定的方法 添加到正确的列表中,例如,如果脚本具有Update方法 定义它被添加到需要更新的脚本列表中 每一帧。
在游戏中,Unity只是遍历这些列表并从中执行方法 - 就这么简单。而且,这就是为什么无所谓 您的Update方法是公开的或私有的。
http://blogs.unity3d.com/2015/12/23/1k-update-calls/
在接口的情况下,我会假设它需要更多,因为需要接口。否则,您只需像任何其他MonoBehaviour方法一样添加方法。
我的假设(可能是错误的),它在这个GameObject上使用了一个基本的GetComponents。然后迭代生成的数组并调用HAS TO BE实现的方法,因为它来自接口。
您可以使用以下内容重现该模式:
NewsData data;
if(GetNews(out data))
{
IGetNews [] getNews = data.gameObject.GetComponents<IGetNews>();
foreach(IGetNews ign in getNews){ ign.SomeNews(); }
}
GetNews是一种检查是否应该将某些新闻发送到该对象的方法。您可以将它想象为Physics.Raycast,它将值赋给RaycastHit。如果该对象是出于任何正当理由接收新闻的话,它会填充数据引用。
答案 1 :(得分:3)
您可以使用反射来获取实现特定接口的程序集中的所有类型,然后实例化这些类型并通过接口调用这些实例上的方法。
var types = this.GetType().Assembly.GetTypes()
.Where(t=>t.GetInterfaces().Contains(typeof(IGetNews)));
foreach (var type in types)
{
var instance = (IGetNews) Activator.CreateInstance(type);
instance.SomeNews("news");
}