Skip to content

Instantly share code, notes, and snippets.

@chiepomme
Last active September 13, 2017 08:18
Show Gist options
  • Save chiepomme/9560002 to your computer and use it in GitHub Desktop.
Save chiepomme/9560002 to your computer and use it in GitHub Desktop.
Unity で使えるシグナルを作りたかった
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> { }
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