Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 统一的简单事件系统_C#_Events_Unity3d - Fatal编程技术网

C# 统一的简单事件系统

C# 统一的简单事件系统,c#,events,unity3d,C#,Events,Unity3d,我试图在Unity(C#方式)中使用事件系统,但在实现它时遇到了问题 大多数示例都显示了一个类,您可以在其中定义处理程序;然后在同一个类中编写与处理程序签名匹配的函数,并将事件作为静态事件编写 public class EventExample : MonoBehaviour { public delegate void ExampleEventHandler(); public static event ExampleEventHandler OneDayPassed;

我试图在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

    }
}
到目前为止还没有问题,但我不确定如何设计它,因此任何特定类型的游戏对象都将订阅此事件。例如,如果您有一个职员类别GO,即工作8到6,并且您在运行时实例化它们;我应该在这个类别的主类中订阅,还是应该创建一个附加到游戏对象预制的脚本来订阅事件

我们的目标是让所有应该在体育中心轮班8到6次的工作人员知道“一天结束”活动何时开始,但我不想订阅我实例化的每一个预制件


据我所知,我应该在预置中附加一个脚本,其中包含所需的代码,但我找不到一个实际的例子来说明这是否是实现的方法。

如果您只谈论几十个订阅者,请不要太担心订阅者的数量。是的,一旦你进入成百上千,优化这个可能是一个好主意,但即使如此。优化的第一条规则:不要优化


因此:只需让每个实例订阅事件并完成它。

您必须使用
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;
}
把它放在游戏物体上。现在在检查器中查看它

您将看到“哇”事件

当“哇”发生时,只需将其他脚本拖到那里,就可以在其他脚本上发生一些事情。

就这么简单。要在BigScript中调用事件,只需

    [Header("Here's a cool event! Drag anything here!")]
    public UnityEvent whoa;
    
    private void YourFunction()
    {
        whoa.Invoke();
    }

在极少数情况下,您可能需要通过代码添加侦听器,而不是简单地在编辑器中拖动它。这是微不足道的:

whoa.AddListener(ScreenMaybeChanged);
(通常情况下,您不必这样做。只需拖动即可连接。我只是为了完整起见才提到这一点。)


就这些

请注意internet上有关此主题的过时示例代码


上面显示了如何连接没有参数的简单函数

如果您确实需要一个参数: 下面是一个示例,其中函数有一个浮点参数:

只需在文件顶部添加以下代码:

[System.Serializable] public class _UnityEventFloat:UnityEvent<float> {}
[System.Serializable]公共类_UnityEventFloat:UnityEvent{}
然后继续正常操作。就这么简单

// ...
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);
    }
}
/。。。
使用UnityEngine.Events;
//将这行神奇的代码添加到顶部。。。
[System.Serializable]公共类_UnityEventFloat:UnityEvent{}
公共课发生了一些事情:单一行为
{
//现在照常进行:
公共单位即使不允许更改长度;
无效处理值(浮点v)
{
// ...
changedLength.Invoke(1.4455f);
}
}
从其他函数拖动到此函数的编辑器插槽时:

一定要使用“动态浮动”部分


(令人困惑的是,您的函数也将列在“静态参数”部分中!这在Unity中是一个巨大的gotchya!)

嗨,Newb'z。这完全是错误的。现在你只需使用
UnityEvent
。你不使用,实际上也不能使用十年前的“旧式”事件。因此,与语言本身的一部分相比,依赖于只在统一中使用的东西更好?嗨@newbiez。是的,这是绝对正确的。你应该明白,你在使用统一,你在使用传统编程的极端扭曲。它不是一个面向对象的系统,它是ECS。考虑一下我最近的问题,Unity有这些“接口”,它们实际上是完全错误的,而C接口中的“接口”是相反的。我不明白。我看过的其他地方都说原生C#events优于UnityEvent,即使在这里,然后这里有一个比较显示原生C#events在这里更好:但奇怪的是,这个问题和评论以及所有的答案现在都在说UnityEvent更好?我完全糊涂了。谢谢Joe,这比使用标准的C#委托和事件系统要简单得多。我唯一担心的是,一旦你习惯了这一点,你就会失去标准的C#方式来做事情……我确实为Unity应用程序和纯C#应用程序编写代码,所以我的“to go”方法通常是使用C#提供的任何本机代码。我假设Unity方法与使用C#中的常规委托和事件一样有效;谢谢嗨,newbiez,传统的c#事件在Unity环境下不起作用,因为它是一个ECS系统。因此,Unity创建了(杰出的)UnityEvent系统。考虑到你在多个系统上工作这一事实——没什么大不了的。你必须是这两方面的专家。这就是生活!我懂了;我确实使用带有事件和委托的常规C#代码实现了我的系统,但这要容易得多,并且与Unity中的其他所有东西一样,与ECS模型兼容。事实上,您必须是一个万事通:)问题:我想了解的是,在使用派生的
UnityEvent
类型(例如,
公共类CustomEvent:UnityEvent
)时,如何在检查器中指定参数值。使用此选项时,检查器会理解签名(字符串、浮点),允许在目标脚本中选择要调用的函数,但不允许在检查器中为这些参数指定值。将stock
UnityEvent
绑定到采用
字符串
参数的函数时,此功能可用。也许没有自定义编辑代码是不可能的?Howdy@PaulBinder(1)当然,在某些情况下,您可以在代码(2)中进行编辑。我在上面的上下文中回答了这个问题