如何传递要添加到 Unity/C# 中的事件的函数?
How do I pass a function to be added to an event in Unity/C#?
我正在尝试创建一些继承 class 结构。在了解了事件之后,我想以某种方式使用它们。我的意图是有一个抽象 class 需要子 classes 来实现 OnDeath UnityEvent。我尝试过使用 System.Func 和 Delegates,但它们都不适合我。我已经包含了我尝试过的内容,以及我在尝试这些内容时收到的错误。有没有一种方法可以让我向事件调用程序添加一个函数?我是不是让这个过程过于复杂了?
澄清一下:
我知道不同的类型,以及这些类型导致此错误的原因。我的问题在于我应该在这里使用哪种类型。我不知道 Unity Action 是什么,或者如果我想使用它,甚至不知道如何定义这样的对象。
使用委托
EntityManager.cs with delegate
using UnityEngine;
using UnityEngine.Events;
using System;
public abstract class EntityManager : MonoBehaviour
{
public EntityManager()
{
if (OnDeathEvent == null)
{
OnDeathEvent = new UnityEvent();
}
OnDeathEvent.AddListener(OnDeath);
}
public abstract bool IsAlive();
public delegate void Function();
public abstract void AddOnDeathListener(Function f);
public abstract void OnDeath();
public UnityEvent OnDeathEvent;
}
EnemyManager.cs with delegate
using System;
public class EnemyManager : EntityManager
{
private Enemy _enemy;
public Enemy Enemy { get => _enemy; set => _enemy = value; }
private void Awake()
{
_enemy = new Enemy();
}
public override bool IsAlive()
{
return Enemy.IsAlive();
}
public void NextEnemy()
{
Enemy = new Enemy();
}
public override void OnDeath()
{
NextEnemy();
}
public override void AddOnDeathListener(Function f)
{
OnDeathEvent.AddListener(f);
// cannot convert from 'EntityManager.Function' to 'UnityEngine.Events.UnityAction'
}
}
使用函数
EntityManager.cs with Func
public abstract void AddOnDeathListener(Func<object> f);
EnemyManager.cs with Func
public override void AddOnDeathListener(Func<object> f)
{
OnDeathEvent.AddListener(f);
// cannot convert from 'System.Func<object>' to 'UnityEngine.Events.UnityAction'
}
编辑: Unity 中的普通函数似乎创建 UnityAction 对象,而不是一般的 Func 对象,这是一个非常重要的区别。通过这个镜头重新定义问题,接受的答案很有意义。
您应该将 AddOnDeathListener
方法更改为采用 UnityAction
而不是 Func
或其他任何方法,因为 UnityEvent
的 AddListener
方法class 将 UnityAction
委托作为参数。
摘要中的代码 class 应如下所示:
public abstract void AddOnDeathListener(UnityAction f);
UnityEvents 与系统命名空间中的 C# 事件不同,UnityAction 与系统命名空间中的 C# 动作不同。但是在您的代码中,您将两者混合在一起,OnDeathEvent
在 UnityEngine.Events
命名空间中,而 Func
在 System
中。您遇到编译器问题的原因是 UnityEvent.AddListener
方法采用 UnityAction
参数,而不是 System.Func
.
要修复,您需要将 OnDeathEvent
切换为 C# 事件,或者将 AddOnDeathListener
更改为将 UnityAction
作为参数。
参考文献:
https://docs.unity3d.com/ScriptReference/Events.UnityEvent.AddListener.html
https://www.jacksondunstan.com/articles/3335
代码示例:
public class CoolAbstract : TestMeAbstract
{
UnityEvent SomeKindOfEvent;
private void Start()
{
SomeKindOfEvent = new UnityEvent();
AddOnDeathListener(() => { Debug.Log("Cool Abstraction"); });
}
private void Update()
{
if(Input.GetKeyDown(KeyCode.A))
{
SomeKindOfEvent.Invoke();
}
}
public override void AddOnDeathListener(UnityAction ua)
{
SomeKindOfEvent.AddListener(ua);
}
}
public abstract class TestMeAbstract : MonoBehaviour
{
public abstract void AddOnDeathListener(UnityAction ua);
}
我正在尝试创建一些继承 class 结构。在了解了事件之后,我想以某种方式使用它们。我的意图是有一个抽象 class 需要子 classes 来实现 OnDeath UnityEvent。我尝试过使用 System.Func 和 Delegates,但它们都不适合我。我已经包含了我尝试过的内容,以及我在尝试这些内容时收到的错误。有没有一种方法可以让我向事件调用程序添加一个函数?我是不是让这个过程过于复杂了?
澄清一下: 我知道不同的类型,以及这些类型导致此错误的原因。我的问题在于我应该在这里使用哪种类型。我不知道 Unity Action 是什么,或者如果我想使用它,甚至不知道如何定义这样的对象。
使用委托
EntityManager.cs with delegate
using UnityEngine;
using UnityEngine.Events;
using System;
public abstract class EntityManager : MonoBehaviour
{
public EntityManager()
{
if (OnDeathEvent == null)
{
OnDeathEvent = new UnityEvent();
}
OnDeathEvent.AddListener(OnDeath);
}
public abstract bool IsAlive();
public delegate void Function();
public abstract void AddOnDeathListener(Function f);
public abstract void OnDeath();
public UnityEvent OnDeathEvent;
}
EnemyManager.cs with delegate
using System;
public class EnemyManager : EntityManager
{
private Enemy _enemy;
public Enemy Enemy { get => _enemy; set => _enemy = value; }
private void Awake()
{
_enemy = new Enemy();
}
public override bool IsAlive()
{
return Enemy.IsAlive();
}
public void NextEnemy()
{
Enemy = new Enemy();
}
public override void OnDeath()
{
NextEnemy();
}
public override void AddOnDeathListener(Function f)
{
OnDeathEvent.AddListener(f);
// cannot convert from 'EntityManager.Function' to 'UnityEngine.Events.UnityAction'
}
}
使用函数
EntityManager.cs with Func
public abstract void AddOnDeathListener(Func<object> f);
EnemyManager.cs with Func
public override void AddOnDeathListener(Func<object> f)
{
OnDeathEvent.AddListener(f);
// cannot convert from 'System.Func<object>' to 'UnityEngine.Events.UnityAction'
}
编辑: Unity 中的普通函数似乎创建 UnityAction 对象,而不是一般的 Func 对象,这是一个非常重要的区别。通过这个镜头重新定义问题,接受的答案很有意义。
您应该将 AddOnDeathListener
方法更改为采用 UnityAction
而不是 Func
或其他任何方法,因为 UnityEvent
的 AddListener
方法class 将 UnityAction
委托作为参数。
摘要中的代码 class 应如下所示:
public abstract void AddOnDeathListener(UnityAction f);
UnityEvents 与系统命名空间中的 C# 事件不同,UnityAction 与系统命名空间中的 C# 动作不同。但是在您的代码中,您将两者混合在一起,OnDeathEvent
在 UnityEngine.Events
命名空间中,而 Func
在 System
中。您遇到编译器问题的原因是 UnityEvent.AddListener
方法采用 UnityAction
参数,而不是 System.Func
.
要修复,您需要将 OnDeathEvent
切换为 C# 事件,或者将 AddOnDeathListener
更改为将 UnityAction
作为参数。
参考文献:
https://docs.unity3d.com/ScriptReference/Events.UnityEvent.AddListener.html https://www.jacksondunstan.com/articles/3335
代码示例:
public class CoolAbstract : TestMeAbstract
{
UnityEvent SomeKindOfEvent;
private void Start()
{
SomeKindOfEvent = new UnityEvent();
AddOnDeathListener(() => { Debug.Log("Cool Abstraction"); });
}
private void Update()
{
if(Input.GetKeyDown(KeyCode.A))
{
SomeKindOfEvent.Invoke();
}
}
public override void AddOnDeathListener(UnityAction ua)
{
SomeKindOfEvent.AddListener(ua);
}
}
public abstract class TestMeAbstract : MonoBehaviour
{
public abstract void AddOnDeathListener(UnityAction ua);
}