Last active
September 13, 2017 08:18
-
-
Save chiepomme/9560002 to your computer and use it in GitHub Desktop.
Unity で使えるシグナルを作りたかった
This file contains 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 ISignal | |
{ | |
void UnsafeSubscribe(Delegate slot, SlotGroup group = null); | |
void UnsafeUnsubscribe(Delegate slot, SlotGroup group = null); | |
} | |
public abstract class SyncSignal : ISignal | |
{ | |
readonly List<Action> Slots = new List<Action>(); | |
public void Publish() | |
{ | |
Slots.ForEach(s => s.Invoke()); | |
} | |
public void Subscribe(Action slot, SlotGroup group = null) | |
{ | |
Slots.Add(slot); | |
if (group != null) group.Add(GetType(), slot); | |
} | |
public void Unsubscribe(Action slot, SlotGroup group = null) | |
{ | |
Slots.Remove(slot); | |
if (group != null) group.Remove(GetType(), slot); | |
} | |
public void UnsafeSubscribe(Delegate slot, SlotGroup group = null) | |
{ | |
Slots.Add((Action) slot); | |
if (group != null) group.Remove(GetType(), slot); | |
} | |
public void UnsafeUnsubscribe(Delegate slot, SlotGroup group = null) | |
{ | |
Slots.Remove((Action) slot); | |
if (group != null) group.Add(GetType(), slot); | |
} | |
} | |
public abstract class SyncSignal<T1> : ISignal | |
{ | |
readonly List<Action<T1>> Slots = new List<Action<T1>>(); | |
public void Publish(T1 arg1) | |
{ | |
Slots.ForEach(s => s.Invoke(arg1)); | |
} | |
public void Subscribe(Action<T1> slot, SlotGroup group = null) | |
{ | |
Slots.Add(slot); | |
if (group != null) group.Add(GetType(), slot); | |
} | |
public void Unsubscribe(Action<T1> slot, SlotGroup group = null) | |
{ | |
Slots.Remove(slot); | |
if (group != null) group.Remove(GetType(), slot); | |
} | |
public void UnsafeSubscribe(Delegate slot, SlotGroup group = null) | |
{ | |
Slots.Add((Action<T1>) slot); | |
if (group != null) group.Remove(GetType(), slot); | |
} | |
public void UnsafeUnsubscribe(Delegate slot, SlotGroup group = null) | |
{ | |
Slots.Remove((Action<T1>) slot); | |
if (group != null) group.Add(GetType(), slot); | |
} | |
} | |
public abstract class SyncSignal<T1, T2> : ISignal | |
{ | |
readonly List<Action<T1, T2>> Slots = new List<Action<T1, T2>>(); | |
public void Publish(T1 arg1, T2 arg2) | |
{ | |
Slots.ForEach(s => s.Invoke(arg1, arg2)); | |
} | |
public void Subscribe(Action<T1, T2> slot, SlotGroup group = null) | |
{ | |
Slots.Add(slot); | |
if (group != null) group.Add(GetType(), slot); | |
} | |
public void Unsubscribe(Action<T1, T2> slot, SlotGroup group = null) | |
{ | |
Slots.Remove(slot); | |
if (group != null) group.Remove(GetType(), slot); | |
} | |
public void UnsafeSubscribe(Delegate slot, SlotGroup group = null) | |
{ | |
Slots.Add((Action<T1, T2>) slot); | |
if (group != null) group.Remove(GetType(), slot); | |
} | |
public void UnsafeUnsubscribe(Delegate slot, SlotGroup group = null) | |
{ | |
Slots.Remove((Action<T1, T2>) slot); | |
if (group != null) group.Add(GetType(), slot); | |
} | |
} | |
public abstract class SyncSignal<T1, T2, T3> : ISignal | |
{ | |
readonly List<Action<T1, T2, T3>> Slots = new List<Action<T1, T2, T3>>(); | |
public void Publish(T1 arg1, T2 arg2, T3 arg3) | |
{ | |
Slots.ForEach(s => s.Invoke(arg1, arg2, arg3)); | |
} | |
public void Subscribe(Action<T1, T2, T3> slot, SlotGroup group = null) | |
{ | |
Slots.Add(slot); | |
if (group != null) group.Add(GetType(), slot); | |
} | |
public void Unsubscribe(Action<T1, T2, T3> slot, SlotGroup group = null) | |
{ | |
Slots.Remove(slot); | |
if (group != null) group.Remove(GetType(), slot); | |
} | |
public void UnsafeSubscribe(Delegate slot, SlotGroup group = null) | |
{ | |
Slots.Add((Action<T1, T2, T3>) slot); | |
if (group != null) group.Remove(GetType(), slot); | |
} | |
public void UnsafeUnsubscribe(Delegate slot, SlotGroup group = null) | |
{ | |
Slots.Remove((Action<T1, T2, T3>) slot); | |
if (group != null) group.Add(GetType(), slot); | |
} | |
} | |
public abstract class SyncSignal<T1, T2, T3, T4> : ISignal | |
{ | |
readonly List<Action<T1, T2, T3, T4>> Slots = new List<Action<T1, T2, T3, T4>>(); | |
public void Publish(T1 arg1, T2 arg2, T3 arg3, T4 arg4) | |
{ | |
Slots.ForEach(s => s.Invoke(arg1, arg2, arg3, arg4)); | |
} | |
public void Subscribe(Action<T1, T2, T3, T4> slot, SlotGroup group = null) | |
{ | |
Slots.Add(slot); | |
if (group != null) group.Add(GetType(), slot); | |
} | |
public void Unsubscribe(Action<T1, T2, T3, T4> slot, SlotGroup group = null) | |
{ | |
Slots.Remove(slot); | |
if (group != null) group.Remove(GetType(), slot); | |
} | |
public void UnsafeSubscribe(Delegate slot, SlotGroup group = null) | |
{ | |
Slots.Add((Action<T1, T2, T3, T4>) slot); | |
if (group != null) group.Remove(GetType(), slot); | |
} | |
public void UnsafeUnsubscribe(Delegate slot, SlotGroup group = null) | |
{ | |
Slots.Remove((Action<T1, T2, T3, T4>) slot); | |
if (group != null) group.Add(GetType(), slot); | |
} | |
} | |
public class SlotGroup | |
{ | |
readonly Dictionary<Type, List<Delegate>> SlotListMap = new Dictionary<Type, List<Delegate>>(); | |
public void Add(Type signalType, Delegate slot) | |
{ | |
if (!SlotListMap.ContainsKey(signalType)) | |
SlotListMap[signalType] = new List<Delegate>(); | |
SlotListMap[signalType].Add(slot); | |
} | |
public void Remove(Type signalType, Delegate slot) | |
{ | |
if (!SlotListMap.ContainsKey(signalType)) return; | |
SlotListMap[signalType].Remove(slot); | |
} | |
public void UnsubscribeAll() | |
{ | |
foreach (var pair in SlotListMap) | |
{ | |
var type = pair.Key; | |
var slots = pair.Value; | |
slots.ForEach(s => SignalStore.Get(type).UnsafeUnsubscribe(s)); | |
} | |
SlotListMap.Clear(); | |
} | |
} | |
public static class SignalStore | |
{ | |
static readonly Dictionary<Type, ISignal> SignalMap = new Dictionary<Type, ISignal>(); | |
public static SignalT Get<SignalT>() where SignalT : class, ISignal, new() | |
{ | |
var type = typeof(SignalT); | |
if (SignalMap.ContainsKey(type)) | |
{ | |
return (SignalT) SignalMap[type]; | |
} | |
else | |
{ | |
var signal = new SignalT(); | |
SignalMap[type] = signal; | |
return signal; | |
} | |
} | |
public static ISignal Get(Type type) | |
{ | |
if (SignalMap.ContainsKey(type)) | |
{ | |
return SignalMap[type]; | |
} | |
else | |
{ | |
var signal = (ISignal) Activator.CreateInstance(type); | |
SignalMap[type] = signal; | |
return signal; | |
} | |
} | |
} | |
public class SignalBehaviour : MonoBehaviour | |
{ | |
protected SlotGroup SignalGroup; | |
protected virtual void Awake() | |
{ | |
SignalGroup = new SlotGroup(); | |
} | |
protected virtual void OnDestroy() | |
{ | |
SignalGroup.UnsubscribeAll(); | |
} | |
} | |
public class IntSignal : SyncSignal<int> { } | |
public class DateTimeSignal : SyncSignal<string, DateTime> { } |
This file contains 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
public class Test : SignalBehaviour | |
{ | |
void Start() | |
{ | |
SignalStore.Get<IntSignal>().Subscribe(i => Debug.Log(i), SignalGroup); | |
SignalStore.Get<IntSignal>().Publish(50); | |
SignalStore.Get<DateTimeSignal>().Subscribe((str, time) => Debug.Log(str + time), SignalGroup); | |
SignalStore.Get<DateTimeSignal>().Publish("テストだよ", DateTime.Now); | |
SignalGroup.UnsubscribeAll(); | |
SignalStore.Get<DateTimeSignal>().Publish("テストだよ", DateTime.Now); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment