C#使用委托创建事件系统

时间:2019-08-28 14:00:31

标签: c# unity3d events delegates

我正在使用Unity制作游戏并为其创建一个简单的事件系统。该系统允许使用回调委托订阅事件。

系统代码在这里:

public static class Events {

#region fields
public delegate void EventCallback();

public static Dictionary<Event, EventCallback> events;

public enum Event {
    PlayerDied,
    EnterGoal,
    ExitGoal
}
#endregion

static Events() {
    Reset();
}

public static void Reset() {
    events = new Dictionary<Event, EventCallback>();
}

public static void SubscribeToEvent(EventCallback callback, Event type) {

    if (!events.ContainsKey(type)) {
        events.Add(type, callback);
    } else {
        events[type] += callback;
    }
}

public static void OverrideSubscription(EventCallback callback, Event type) {

    if (!events.ContainsKey(type)) {
        events.Add(type, callback);
    } else {
        events[type] = callback;
    }
}
public static void UnsubscribeFromEvent(EventCallback callback, Event type) {
    if (events.ContainsKey(type)) {
        events[type] -= callback;
    }
}

public static void FireEvent(Event type) {

    if (!events.ContainsKey(type)) {
        return;
    }

    events[type]?.Invoke();
}
}

我的问题是这样

在游戏中,订阅某个事件的对象经常会被销毁(因此无效),但回调仍被调用。

为了证明这一点,我为此进行了测试。以下2个测试失败。

[Test]
    public void CallbackIsNotCalledAfterReassigning() {

        Events.SubscribeToEvent(callbacks.A, Events.Event.PlayerDied);

        // Reassign
        callbacks = new CallbackContainer();

        Events.FireEvent(Events.Event.PlayerDied);

        Assert.AreEqual(0, callbacks.a, "Test function was called after reassigning");
        Assert.AreEqual(0, a, "Old instance method is still being called");
    }

    [Test]
    public void CallbackIsNotCalledAfterNullifying() {

        Events.SubscribeToEvent(callbacks.A, Events.Event.PlayerDied);

        // Nullify
        callbacks = null;

        Events.FireEvent(Events.Event.PlayerDied);

        Assert.AreEqual(0, a, "Test function was not called");
    }

而CallbackContainer类在这里:

public class CallbackContainer {

    public int a, b, c;

    public CallbackContainer() {
        int a = 0;
        int b = 0;
        int c = 0;
    }

    public Action TestFunction;

    public void A() {
        EventsTest.a++;
        a++;
    }
    public void B() {
        EventsTest.b++;
        b++;
    }
    public void C() {
        EventsTest.c++;
        c++;
    }
}

是否有解决此问题的方法?有没有更好,更正确的方法来创建事件系统?

任何帮助或建议都值得赞赏。

1 个答案:

答案 0 :(得分:0)

我忘记了Unity自己的委托OnDestroy,该委托在对象取消样式化或加载另一个场景之前被调用。