Skip to content

Instantly share code, notes, and snippets.

@adammyhre
Created November 12, 2023 13:37
Show Gist options
  • Save adammyhre/353195d4870e8fd0cc0028659e66f208 to your computer and use it in GitHub Desktop.
Save adammyhre/353195d4870e8fd0cc0028659e66f208 to your computer and use it in GitHub Desktop.
Generic Observer
using System;
using System.Reflection;
using UnityEngine;
using UnityEngine.Events;
#if UNITY_EDITOR
using UnityEditor.Events;
#endif
[Serializable]
public class Observer<T> {
[SerializeField] T value;
[SerializeField] UnityEvent<T> onValueChanged;
public T Value {
get => value;
set => Set(value);
}
public static implicit operator T(Observer<T> observer) => observer.value;
public Observer(T value, UnityAction<T> callback = null) {
this.value = value;
onValueChanged = new UnityEvent<T>();
if (callback != null) onValueChanged.AddListener(callback);
}
public void Set(T value) {
if (Equals(this.value, value)) return;
this.value = value;
Invoke();
}
public void Invoke() {
Debug.Log($"Invoking {onValueChanged.GetPersistentEventCount()} listeners");
onValueChanged.Invoke(value);
}
public void AddListener(UnityAction<T> callback) {
if (callback == null) return;
if (onValueChanged == null) onValueChanged = new UnityEvent<T>();
#if UNITY_EDITOR
UnityEventTools.AddPersistentListener(onValueChanged, callback);
#else
onValueChanged.AddListener(callback);
#endif
}
public void RemoveListener(UnityAction<T> callback) {
if (callback == null) return;
if (onValueChanged == null) return;
#if UNITY_EDITOR
UnityEventTools.RemovePersistentListener(onValueChanged, callback);
#else
onValueChanged.RemoveListener(callback);
#endif
}
public void RemoveAllListeners() {
if (onValueChanged == null) return;
#if UNITY_EDITOR
FieldInfo fieldInfo = typeof(UnityEventBase).GetField("m_PersistentCalls", BindingFlags.Instance | BindingFlags.NonPublic);
object value = fieldInfo.GetValue(onValueChanged);
value.GetType().GetMethod("Clear").Invoke(value, null);
#else
onValueChanged.RemoveAllListeners();
#endif
}
public void Dispose() {
RemoveAllListeners();
onValueChanged = null;
value = default;
}
}
@Ddemon26
Copy link

Ddemon26 commented Oct 4, 2024

Nice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment