问题描述
我正在尝试在 Unity 中使用事件系统(C# 方式),但在实现它时遇到了问题.
I am trying to use the event system in Unity (the C# way), but I am having problems to implement it.
大多数示例都显示了一个类,您可以在其中定义处理程序;然后你在同一个类中编写与处理程序签名匹配的函数,并将事件编写为静态
Most of the examples, show one class, where you define the handler; then you write in the same class, the function that match the signature of the handler, and you write the events as static
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();
}
}
然后在另一个类中,您订阅事件,创建一个实际执行某些操作的函数
Then in another class, you subscribe to the events, creating a function that actually do something
public class EntityWatcher: MonoBehaviour
{
void Start()
{
EventExample.OneDayPassed += this.PrepareNextDay;
}
public void PrepareNextDay()
{
// Do other stuff that happen after the day is done
}
}
到目前为止没有问题,但我不确定如何设计它,因此任何特定类型的游戏对象都将订阅此事件.例如,如果您有一个 GO 的人员类别,即 8 到 6 人工作,并且您在运行时实例化它们;我应该在这个类别的主类中订阅,还是应该创建一个附加到游戏对象预制件的脚本来订阅事件?
So far no problems, but I am not sure how do I design this, so any GameObject of a particular type, will subscribe to this event. For example, if you have a staff category of GO, that is working 8 to 6, and you instantiate them at runtime; should I subscribe in the main class of this category, or should I create a script that I attach to the Game Object prefab, that subscribe to the event?
目标是所有应该在体育中心轮班工作的员工都知道一天结束"事件何时开始,但我不想订阅我实例化的每个预制件.
The objective is that all the staff members that should do a 8 to 6 shift at the sport center, know when the "day is done" event fire up, but I don't want to subscribe every single prefab that I instantiate.
根据我的理解,我应该在预制件上附加一个包含所需代码的脚本,但我找不到一个实际示例来说明这是否确实是这样做的方法.
From my understanding, I should attach a script with the needed code on the prefab, but I can't find a practical example that show if that is in fact the way to do it.
推荐答案
您必须使用 UnityEvent
.
public UnityEvent whoa;
这很容易.
制作脚本 BigScript.cs
Make a script 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;
}
把它放在一个游戏对象上.现在在检查器中查看.
Put it on a game object. Now look at it in the Inspector.
您将看到哇"活动.
就是这么简单.要在 BigScript 中调用事件,只需
It's that simple. To call the event in BigScript, it is just
[Header("Here's a cool event! Drag anything here!")]
public UnityEvent whoa;
private void YourFunction()
{
whoa.Invoke();
}
在极少数情况下,您可能需要通过代码添加一个监听器,而不是简单地将它拖到编辑器中.这是微不足道的:
In rare cases you may need to add a listener via code rather than simply dragging it in the Editor. This is trivial:
whoa.AddListener(ScreenMaybeChanged);
(通常你不应该这样做.只需拖动即可连接.我只是为了完整性才提到这一点.)
(Normally you should never have to do that. Simply drag to connect. I only mention this for completeness.)
仅此而已.
请注意互联网上有关此主题的过时示例代码.
Be aware of out of date example code regarding this topic on the internet.
上面展示了如何连接没有参数的简单函数.
这是一个函数有一个 FLOAT 参数的例子:
Here is an example where the function has ONE FLOAT argument:
只需在文件顶部添加此代码:
Simply add THIS CODE at the top of the file:
[System.Serializable] public class _UnityEventFloat:UnityEvent<float> {}
然后照常进行.就这么简单.
then proceed as normal. It's that easy.
// ...
using UnityEngine.Events;
// add this magic line of code up top...
[System.Serializable] public class _UnityEventFloat:UnityEvent<float> {}
public class SomeThingHappens : MonoBehaviour
{
// now proceed as usual:
public _UnityEventFloat changedLength;
void ProcessValues(float v)
{
// ...
changedLength.Invoke(1.4455f);
}
}
当您从其他函数拖动到此函数的编辑器插槽时:
When you drag from your other function to the Editor slot on this function:
一定要使用动态浮动"部分.
Be certain to use the section - "Dynamic float".
(令人困惑的是,您的函数也将在静态参数"部分列出!这是 Unity 中的一个巨大问题!)
(Confusingly your function will also be listed in the "Static Parameters" section! That is a huge gotchya in Unity!)
这篇关于Unity 中的简单事件系统的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!