Unity中的简单事件系统
我试图在Unity中使用事件系统(C#方式),但我遇到了实现它的问题。
大多数示例显示了一个类,您可以在其中定义处理程序; 然后你在相同的类中编写,匹配处理程序签名的函数,并将事件写为静态
public class EventExample : MonoBehaviour { public delegate void ExampleEventHandler(); public static event ExampleEventHandler OneDayPassed; public static void NextTurn() { // do stuff then send event if (OneDayPassed != null) OneDayPassed(); } }
然后在另一个类中,您订阅事件,创建一个实际执行某些操作的函数
public class EntityWatcher: MonoBehaviour { void Start() { EventExample.OneDayPassed += this.PrepareNextDay; } public void PrepareNextDay() { // Do other stuff that happen after the day is done } }
到目前为止没有问题,但我不知道如何设计这个,所以任何特定类型的GameObject都会订阅此事件。 例如,如果你有一个GO职员类别,那就是工作8到6,你在运行时实例化它们; 我应该订阅这个类别的主类,还是应该创建一个附加到游戏对象预制件的脚本,订阅该事件?
目标是所有应该在体育中心进行8到6class的工作人员,知道“完成日期”事件何时启动,但我不想订阅我实例化的每一个预制件。
根据我的理解,我应该在预制件上添加一个带有所需代码的脚本,但我找不到一个实际的例子来说明这是否实际上是这样做的。
您必须使用UnityEvent
。
public UnityEvent whoa;
这可不容易。 制作一个脚本BigScript.cs
using UnityEngine; using System.Collections; using UnityEngine.Events; public class BigScript:MonoBehaviour { [Header("Here's a cool event! Drag anything here!")] public UnityEvent whoa; }
把它放在游戏对象上。 现在在Inspector中查看它 。 好吧?
只需将其他脚本拖到那里,就可以在发生“哇哇”的时候发生一些事情。
就这么简单。 要在BigScript中调用事件,它就是
public class BigScript:MonoBehaviour { [Header("Here's a cool event! Drag anything here!")] public UnityEvent whoa; private void YourFunction() { whoa.Invoke(); }
(如果你愿意, if (whoa!=null) whoa.Invoke();
)
在极少数情况下,您可能需要通过代码添加侦听器。
(我的意思是,而不是简单地在编辑器中拖动它。)
现在这很简单。 请注意互联网上过时的示例代码。
whoa.AddListener(ScreenMaybeChanged);
要明确: 永远不要那样做 – 只需拖动即可连接。 我只是提到完整性。
这里的所有都是它的。
请注意互联网上有关此主题的过时示例代码。*
以上显示了如何连接没有参数的简单函数。
如果你确实需要一个参数:
函数具有ONE FLOAT参数的示例:
只需在文件顶部添加此代码:
[System.Serializable] public class _UnityEventFloat:UnityEvent {}
那你就定了。
... using UnityEngine.Events; // magic line of code... [System.Serializable] public class _UnityEventFloat:UnityEvent {} public class SomeThingHappens : MonoBehaviour { public _UnityEventFloat changedLength; public _UnityEventFloat changedHeight; ... and then ... void ProcessValues(float v) { .... if (changedLength != null) changedLength.Invoke(1.4455f); } }
当您从其他function拖动到此function的编辑器插槽时:
绝对确保使用顶部的那些 – “动态浮动”。
令人困惑的是,您的function也将列在较低的“静态参数”部分中!
这是团结中的巨大骗局!
如果你只谈几十个,不要太担心订阅者的数量。 是的,一旦你进入数百或数千,优化它可能是一个好主意,但即便如此。 优化的第一条规则:不优化。
所以:只需让每个实例订阅该事件并完成它。