简体   繁体   English

C# class inheritance 带有 ScriptableObject UnityEvents 和不同类型的 UnityActions

[英]C# class inheritance with ScriptableObject UnityEvents and differently-typed UnityActions

I'm creating custom UnityEvents for a game.我正在为游戏创建自定义 UnityEvents。 The base class looks like this:基础 class 看起来像这样:

public class EventSO : ScriptableObject
{
    List<UnityAction> listeners = new List<UnityAction>();

    public virtual void Raise() { ... }
    public virtual void AddListener(UnityAction listener) { ... }
    public virtual void RemoveListener(UnityAction listener) { ... }
}

Sometimes I want to pass variables to an event.有时我想将变量传递给事件。 So I inherit:所以我继承:

public class FloatEventSO : EventSO
{
    List<UnityAction<float>> listeners = new List<UnityAction<float>>();

    public override void Raise(float f) { ... }
    public override void AddListener(UnityAction<float> listener) { ... }
    public override void RemoveListener(UnityAction<float> listener) { ... }
}

My goal is to be able to create ScriptableObjects for individual events I can then assign and invoke: a good example for a Float event might be to communicate game times.我的目标是能够为我可以分配和调用的单个事件创建 ScriptableObjects:Float 事件的一个很好的例子可能是传达游戏时间。 So, a ScriptableObject named "OnEveryHalfSec", for example.因此,例如,名为“OnEveryHalfSec”的 ScriptableObject。

The first problem with this approach is that I'll need to make a new class for each combination of variables passed to an event: UnityAction<float, int>, UnityAction<float, string>... and so on.这种方法的第一个问题是,我需要为传递给事件的每个变量组合创建一个新的 class:UnityAction<float, int>、UnityAction<float, string>... 等等。

The second problem is that I can't override the base class like I've shown above;第二个问题是我无法像上面显示的那样覆盖基数 class; Raise(float) can't override Raise(). Raise(float) 不能覆盖 Raise()。 So I have to re-define on every class.所以我必须在每个 class 上重新定义。

Is there a better way to approach this problem?有没有更好的方法来解决这个问题?

It looks like you should define看起来你应该定义

 public override void Raise(float f) {... }

as作为

 public virtual void Raise(float f) {... } in the base class

You didn't put "(float f)" in the base class您没有将“(float f)”放入基数 class

You want to use generics !你想使用generics

Have a base class like eg有一个基地 class 像例如

public abstract ParameterEventSO<T> : ScriptableObject
{
    List<UnityAction<T>> listeners = new List<UnityAction<T>>();

    public virtual void Raise(T value) 
    {
        foreach(var listener in listeners)
        {
            listener?.Invoke (value);
        }
    }
    public virtual void AddListener(UnityAction<T> listener)
    {
        listeners.Add(listener);
    }
    public virtual void RemoveListener(UnityAction<T> listener)
    {
        listeners.Remove(listener);
    }
}

Now you can have as many derived classes as you need with specific types like eg现在您可以根据需要使用特定类型的派生类,例如

[CreateAssetMenu]
public class FloatEvent : ParameterEventSO<float> { }

or或者

[CreateAssetMenu]
public class IntListEvent : ParameterEventSO<List<int>> { }

or also或者还有

public class CustomArgs
{
    public Vector3 Position;
    public string Name;
    public DateTime TimeStamp;
}

[CreateAssetMenu]
public class CustomArgsEvent : ParameterEventSO<CustomArgs> { }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM