たとえば、クラスが別のクラスのメソッドを呼び出したい場合、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 つの部分。
仲介モードと似ている点ですが、グローバル イベントは仲介として機能して、イベントの登録と外部への呼び出しを提供し、クラス間の分離の問題を解決します。
デモ