Unity有一个“接口”:
IPointerDownHandler
(doco)
您只需实现OnPointerDown...
public class Whoa:MonoBehaviour,IPointerDownHandler
{
public void OnPointerDown (PointerEventData data)
{ Debug.Log("whoa!"); }
}
而Unity将在任何这样的行为中“神奇地”调用OnPointerDown
。
您不必注册它们,设置事件,也不必做任何其他事情。
从语法上讲,您只需将“IPInterDownHandler”和“public void on PointerDown”添加到类中,就可以神奇地获得这些消息。
(如果你不是Unity开发人员-甚至在游戏运行时突然在编辑器中添加一个,它也会起作用!)
所以,我想这样做:
public interface IGetNews
{
void SomeNews(string s);
}
然后我可以向任何MonoBehavior添加SomeNews
。
(顺便说一句:我觉得他们不应该称这些“接口”,因为它根本不像接口——它有点相反!我想,你可以说它们神奇地从多个抽象类继承。)
旁白:
如果你以前没有使用过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");
}
}
你基本上是在“注册”你的呼叫,你确实是在利用神奇的统一使用——不管它是什么。但是我想直接使用魔法。
当涉及到XXXUpdate、OnCollisionXXX和其他单行为时,Unity注册的方式并不像人们普遍认为的那样是反射,而是一些内部编译过程。
不,Unity不使用System.反思找到一个神奇的方法,每次它都需要调用一个。
相反,第一次访问给定类型的MonoBehavior时,将通过脚本运行时(Mono或IL2CPP)检查底层脚本是否定义了任何神奇的方法,并缓存该信息。如果MonoBehavior具有特定的方法,则会将其添加到适当的列表中,例如,如果脚本定义了更新方法,则会将其添加到每个帧都需要更新的脚本列表中。
在游戏过程中,Unity只是在这些列表中迭代并执行其中的方法——就这么简单。另外,这就是为什么更新方法是公共的还是私有的并不重要。
http://blogs.unity3d.com/2015/12/23/1k-update-calls/
在接口的情况下,我假设它做得更多,因为接口是必需的。否则,您只需像添加任何其他MonoBehavior方法一样添加该方法。
我的假设(这可能是错误的),它在这个游戏对象上使用了一个基本的GetComponents。然后迭代生成的数组,并调用必须实现的方法,因为它来自接口。
您可以使用以下方法复制该模式:
NewsData data;
if(GetNews(out data))
{
IGetNews [] getNews = data.gameObject.GetComponents<IGetNews>();
foreach(IGetNews ign in getNews){ ign.SomeNews(); }
}
GetNews是一个检查是否应该向对象发送某些新闻的方法。你可以把它想象成物理。为光线投射命中指定值的光线投射。在这里,如果该对象出于任何正当理由要接收新闻,它将填充一个数据引用。
您可以使用反射获取实现特定接口的程序集中的所有类型,然后实例化这些类型,并通过接口调用这些实例上的方法。
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");
}