Unity はグローバル イベントを通じてプロジェクトを切り離します

たとえば、クラスが別のクラスのメソッドを呼び出したい場合、A は B のメソッドを呼び出したいとします。
方法 1: 参照
最も単純な方法は、A がクラス B への参照を保持する、つまり A が B のメンバー オブジェクトを所有することです。
方法 2: デザイン モード (中間モード)
、または A と B が同じオブジェクト C に属し、QQ グループなどのオブジェクト C (中間モード) を通じて相互に呼び出します。A と B にはお互いのフレンドがいませんが、両方とも同じ QQ グループ C であれば、C で互いに会話できます。
方法 3: 静的 (通常はシングルトン モード、B は管理クラスなど)
B のメソッドを静的メソッドとして設定します。
ただし、プロジェクトではカテゴリが N 個以上あり、A と B はまったく無関係であり、相互に参照することは適切ではなく、ツール クラスではないため、静的メソッドとして設定すべきではありません。このとき、A と B を接続するにはどうすればよいでしょうか。
答えは、グローバル イベント システムを使用することです。
グローバルにアクセスできるイベントのリストを抽出します (辞書)

public class EventManager : MonoBehaviour
{
    
    

    public static Dictionary<EventType, List<Delegate>> EventDic = new Dictionary<EventType, List<Delegate>>();

    public delegate void CallBack();
    public delegate void CallBack<T>(T parameter);

    public static void AddListener(EventType eventType, CallBack callBack)
    {
    
    
        if (EventDic.ContainsKey(eventType))
        {
    
    
            EventDic[eventType].Add(callBack);
        }
        else
        {
    
    
            EventDic.Add(eventType, new List<Delegate>() {
    
     callBack });
        }
    }

    public static void RemoveListener(EventType eventType, CallBack callBack)
    {
    
    
        if (EventDic.ContainsKey(eventType))
        {
    
    
            CallBack currentCallBack = null;
            foreach (var item in EventDic[eventType])
            {
    
    
                currentCallBack = item as CallBack;
                if (currentCallBack == callBack)
                {
    
    
                    currentCallBack = callBack;
                }
            }
            if (currentCallBack != null)
            {
    
    
                EventDic[eventType].Remove(callBack);
            }
            if (EventDic[eventType].Count == 0)
            {
    
    
                EventDic.Remove(eventType);
            }
        }
        else
        {
    
    
            throw new Exception("当前系统未注册该事件");
        }
    }

    public static void AddListener<T>(EventType eventType, CallBack<T> callBack)
    {
    
    
        if (EventDic.ContainsKey(eventType))
        {
    
    
            EventDic[eventType].Add(callBack);
        }
        else
        {
    
    
            EventDic.Add(eventType, new List<Delegate>() {
    
     callBack });
        }
    }

    public static void RemoveListener<T>(EventType eventType, CallBack<T> callBack)
    {
    
    
        if (EventDic.ContainsKey(eventType))
        {
    
    
            CallBack<T> currentCallBack = null;
            foreach (var item in EventDic[eventType])
            {
    
    
                currentCallBack = item as CallBack<T>;
                if (currentCallBack == callBack)
                {
    
    
                    currentCallBack = callBack;
                }
            }
            if (currentCallBack != null)
            {
    
    
                EventDic[eventType].Remove(callBack);
            }
            if (EventDic[eventType].Count == 0)
            {
    
    
                EventDic.Remove(eventType);
            }
        }
        else
        {
    
    
            throw new Exception("当前系统未注册该事件");
        }
    }



    public static void Dispatch(EventType eventType)
    {
    
    
        if (EventDic.ContainsKey(eventType))
        {
    
    
            CallBack callBack;
            foreach (var item in EventDic[eventType])
            {
    
    
                callBack = item as CallBack;
                if (callBack != null)
                {
    
    
                    callBack();
                }
            }
        }
        else
        {
    
    
            throw new Exception("当前事件系统不包含该事件");
        }
    }

    public static void Dispatch<T>(EventType eventType, T parameter)
    {
    
    
        if (EventDic.ContainsKey(eventType))
        {
    
    
            CallBack<T> callBack;
            foreach (var item in EventDic[eventType])
            {
    
    
                callBack = item as CallBack<T>;
                if (callBack != null)
                {
    
    
                    callBack(parameter);
                }
            }
        }
        else
        {
    
    
            throw new Exception("当前事件系统不包含该事件");
        }
    }

}

public class EventData 
{
    
    
    public int money;
}

public enum EventType
{
    
    
    AddMoney,
    AddMoneyWithParameter,
    AddMoneyWithEventData,
}

インデックスは列挙型で、値はデリゲート型です。
次に、A と B は、外部から呼び出す必要があるメソッドを登録します。
以下は従業員の上司の例です。
上司はお金を集める方法を提供し、従業員はそれを呼び出す責任があります。

public class Boss: MonoBehaviour
{
    
    
    public Button AddListenerButton;
    public Button RemoveListenerButton;

    void Awake()
    {
    
    
        AddListenerButton.onClick.AddListener(() =>
        {
    
    
            EventManager.AddListener(EventType.AddMoney, GetMoney);
            EventManager.AddListener<int>(EventType.AddMoneyWithParameter, GetMoneyWihtPrameter);
            EventManager.AddListener<EventData>(EventType.AddMoneyWithEventData, GetmoneyWithEventData);
        });

        RemoveListenerButton.onClick.AddListener(() =>
        {
    
    
            EventManager.RemoveListener(EventType.AddMoney, GetMoney);
            EventManager.RemoveListener<int>(EventType.AddMoneyWithParameter, GetMoneyWihtPrameter);
            EventManager.RemoveListener<EventData>(EventType.AddMoneyWithEventData, GetmoneyWithEventData);
        });
    }
    void GetMoney()
    {
    
    
        Debug.Log("收到用户购买的资金,员工真棒");
    }
    void GetMoneyWihtPrameter(int money)
    {
    
    
        Debug.Log("收到用户购买的资金,员工真棒,收入赚了  " + money);
    }

    void GetmoneyWithEventData(EventData data) 
    {
    
    
        Debug.Log("通过事件数据收到用户购买的资金,员工真棒,收入赚了  " + data.money);
    }
}

public class Staff : MonoBehaviour
{
    
    
    public Button BuyButton;

    public Button BuyButtonWithParameter;

    public Button BuyButtonWithEventData;

    private void Start()
    {
    
    
        BuyButton.onClick.AddListener(() =>
        {
    
    
            EventManager.Dispatch(EventType.AddMoney);
        });
        BuyButtonWithParameter.onClick.AddListener(() =>
        {
    
    
            EventManager.Dispatch(EventType.AddMoneyWithParameter, 100);
        });
        BuyButtonWithEventData.onClick.AddListener(() =>
        {
    
    
            EventManager.Dispatch(EventType.AddMoneyWithEventData, new EventData() {
    
     money = 200});
        });
    }
}

実際の効果は次のように示されます。
ここに画像の説明を挿入
概要:
ジェネリックはグローバル イベントで使用され (データ型は呼び出し時に決定されます)、親クラスはすべてのサブクラスを受け入れることができます (デリゲートはすべてのサブクラスを受け取ることができます)、オーバーロード (登録されたメソッドはパラメータを持つことができ、パラメータを持たないこともできます) 3 つの部分。
仲介モードと似ている点ですが、グローバル イベントは仲介として機能して、イベントの登録と外部への呼び出しを提供し、クラス間の分離の問題を解決します。
デモ

おすすめ

転載: blog.csdn.net/qq_40629631/article/details/121545729
おすすめ