C# class 继承 ScriptableObject UnityEvents 和不同类型的 UnityActions

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

我正在为游戏创建自定义 UnityEvents。基础 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) { ... }
}

有时我想将变量传递给事件。所以我继承:

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) { ... }
}

我的目标是能够为我可以分配和调用的单个事件创建 ScriptableObjects:浮动事件的一个很好的例子可能是传达游戏时间。因此,例如,名为“OnEveryHalfSec”的 ScriptableObject。

这种方法的第一个问题是我需要为传递给事件的每个变量组合创建一个新的 class:UnityAction, UnityAction。 ..等等。

第二个问题是我无法像上面显示的那样覆盖基础 class; Raise(float) 不能覆盖 Raise()。所以我必须重新定义每个 class.

有没有更好的方法来解决这个问题?

看来你应该定义

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

作为

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

你没有把 "(float f)" 放在基数中 class

您想使用 generics!

有一个基础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);
    }
}

现在您可以拥有任意数量的派生 classes 以及特定类型,例如

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

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

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

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