前面幾篇基礎文章
Unity遊戲框架搭建筆記---測試驅動,UnityTestRunner
Unity遊戲框架搭建筆記---強類型消息系統(私以爲最佳實踐)
局部的消息系統,慣例先放使用方法。
public class Test : MonoBehaviour
{
private IEventBroadcaster broadcaster;
private EventBroadcaster _eventBroadcaster;
void Start()
{
_eventBroadcaster = new EventBroadcaster();
broadcaster = _eventBroadcaster;
broadcaster.Register<string>(EventBroadcaster.NAME_CHANGE,OnNameChange);
}
private int i;
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
i++;
_eventBroadcaster.Name = i.ToString();
}
}
private void OnNameChange(string name)
{
print(name);
}
}
//需要繼承IEventBroadcaster
public class EventBroadcaster : IEventBroadcaster
{
public const string NAME_CHANGE = "NAME_CHANGE";
private string name;
public string Name
{
get => name;
set
{
name = value;
LocalEventService.TriggerEvent(this, NAME_CHANGE, name);
}
}
}
實現思路跟全局的消息系統類似,只不過加了個IEventBroadcaster來做key,下面放代碼
class MulCallbackContainer<T> : ICallBackBase
{
public string Tag;
public Action<T> Action;
public MulCallbackContainer(string tag, Action<T> action)
{
Tag = tag;
Action = action;
}
public void Trigger(string tag, T value)
{
if(tag != Tag ) return;
Action(value);
}
}
internal static void Register<T>(IEventBroadcaster eventBroadcaster, string tag, Action<T> cb)
{
var type = typeof(T);
if (!_subscribersDic.TryGetValue(eventBroadcaster, out var dic))
{
dic = new Dictionary<Type, List<ICallBackBase>>();
_subscribersDic.Add(eventBroadcaster, dic);
}
if (!dic.TryGetValue(type, out var list))
{
list = new List<ICallBackBase>();
dic.Add(type, list);
}
if (!CallBackExists(list, tag, cb))
{
ICallBackBase callBackBase = new MulCallbackContainer<T>(tag, cb);
list.Add(callBackBase);
}
else
{
Log.Warning("repeated register....");
}
}
public static void TriggerEvent<T>(IEventBroadcaster eventBroadcaster, string tag, T value)
{
var type = typeof(T);
if (!_subscribersDic.TryGetValue(eventBroadcaster, out var dic)) return;
if (!dic.TryGetValue(type, out var list)) return;
// ReSharper disable once PossibleInvalidCastExceptionInForeachLoop
foreach (MulCallbackContainer<T> callbackContainer in list)
{
callbackContainer.Trigger(tag, value);
}
}
只放了註冊和觸發,並沒有很複雜的邏輯,下面放單元測試代碼
[Test]
public void 局部事件()
{
IEventBroadcaster eventBroadcaster = Substitute.For<IEventBroadcaster>();
eventBroadcaster.Register<AMsg>(AMsgCB);
eventBroadcaster.TriggerEvent(new AMsg());
Assert.IsTrue(IsCall);
}
private bool IsCall = false;
private void AMsgCB(AMsg obj)
{
IsCall = true;
}
All Success! 消息系統基本就這樣