Last active
April 7, 2022 01:48
-
-
Save SradnickDev/e051871b27282d190086a08140a271db to your computer and use it in GitHub Desktop.
Static generic message hub / message system.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using UnityEngine; | |
public interface IMessage { } | |
public static class MessageHub | |
{ | |
public delegate void MessageSubscription<in T>(T message) where T : IMessage; | |
private const int MaxPublishDepth = 10; | |
private static int m_publishDepth = 0; | |
private static readonly HashSet<Type> m_subscribedTypes = new HashSet<Type>(); | |
private static class TypedMessageHub<TMessage> where TMessage : IMessage | |
{ | |
private const int DefaultBufferSize = 10; | |
private static readonly List<MessageSubscription<TMessage>> m_subscriptions = new List<MessageSubscription<TMessage>>(DefaultBufferSize); | |
private static readonly List<MessageSubscription<TMessage>> m_buffer = new List<MessageSubscription<TMessage>>(DefaultBufferSize); | |
public static void Subscribe(MessageSubscription<TMessage> subscription) | |
{ | |
m_subscriptions.Add(subscription); | |
} | |
public static void Unsubscribe(MessageSubscription<TMessage> subscription) | |
{ | |
m_subscriptions.Remove(subscription); | |
} | |
public static void Publish(TMessage message) | |
{ | |
if (m_subscriptions.Count > m_buffer.Count) | |
{ | |
m_buffer.Capacity = m_subscriptions.Count * 2; | |
} | |
var iSubscriptionCount = m_subscriptions.Count; | |
for (var i = 0; i < iSubscriptionCount; i++) | |
{ | |
m_buffer.Add(m_subscriptions[i]); | |
} | |
for (var i = 0; i < iSubscriptionCount; i++) | |
{ | |
m_buffer[i]?.Invoke(message); | |
} | |
m_buffer.Clear(); | |
} | |
public static void Clear() | |
{ | |
m_subscriptions.Clear(); | |
} | |
} | |
public static void Subscribe<T>(MessageSubscription<T> subscription) where T : IMessage | |
{ | |
m_subscribedTypes.Add(typeof(T)); | |
TypedMessageHub<T>.Subscribe(subscription); | |
} | |
public static void Unsubscribe<T>(MessageSubscription<T> subscription) where T : IMessage | |
{ | |
TypedMessageHub<T>.Unsubscribe(subscription); | |
} | |
public static void Publish<T>(T message) where T : IMessage | |
{ | |
m_publishDepth++; | |
if (m_publishDepth < MaxPublishDepth) | |
{ | |
TypedMessageHub<T>.Publish(message); | |
m_publishDepth--; | |
} | |
else | |
{ | |
Debug.LogError("[MessageHub] Max publish depth reached, make sure you don't stuck in an infinity publishing loop, otherwise increase max depth."); | |
} | |
} | |
public static void Clear<T>() where T : IMessage | |
{ | |
TypedMessageHub<T>.Clear(); | |
} | |
public static void ClearAll() | |
{ | |
foreach (var subscribedType in m_subscribedTypes) | |
{ | |
var type = typeof(TypedMessageHub<>).MakeGenericType(subscribedType); | |
var methodInfo = type.GetMethod("Clear"); | |
methodInfo?.Invoke(null, null); | |
} | |
} | |
} | |
//--------------- Example --------------- | |
public class GameEventMessage : IMessage | |
{ | |
public int SomeValue; | |
public GameObject Fo; | |
} | |
public class Example : MonoBehaviour | |
{ | |
private void OnEnable() | |
{ | |
MessageHub.Subscribe<GameEventMessage>(OnGameEventMessageReceived); | |
MessageHub.Publish(new GameEventMessage() | |
{ | |
Fo = this.gameObject, | |
SomeValue = 10 | |
}); | |
} | |
private void OnDisable() | |
{ | |
MessageHub.Unsubscribe<GameEventMessage>(OnGameEventMessageReceived); | |
} | |
public void OnGameEventMessageReceived(GameEventMessage message) | |
{ | |
var value = message.SomeValue; | |
var target = message.Fo; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment