I've got this class that takes works with generics. I want to run an event any time you modify anything within T
. Say you have a class called Settings
with a few bools inside and pass that in as T
. I want to call the DataVariable<>
onChanged
event any time any of the bools were modified but I'm not sure how or if it's even possible.
using System;
using UnityEngine;
namespace Udon {
[Serializable]
public class DataReference<T> {
[SerializeField] private bool useConstant;
[SerializeField] private DataVariable<T> variable;
[SerializeField] private T constantValue;
private T cachedValue;
public T GetValue => useConstant ? constantValue : variable.value;
public T SetValue {
get {
if (useConstant) return constantValue;
variable.onChanged?.Raise();
return variable.value;
}
}
}
}
If possible this would mean turning the set and get values into one unified property called Value
. How do I check if variables inside T
were changed without knowing what T
is? If there is a better way to do this I'd love to know too.
Full Codebase available at:
I've got this class that takes works with generics. I want to run an event any time you modify anything within T
. Say you have a class called Settings
with a few bools inside and pass that in as T
. I want to call the DataVariable<>
onChanged
event any time any of the bools were modified but I'm not sure how or if it's even possible.
using System;
using UnityEngine;
namespace Udon {
[Serializable]
public class DataReference<T> {
[SerializeField] private bool useConstant;
[SerializeField] private DataVariable<T> variable;
[SerializeField] private T constantValue;
private T cachedValue;
public T GetValue => useConstant ? constantValue : variable.value;
public T SetValue {
get {
if (useConstant) return constantValue;
variable.onChanged?.Raise();
return variable.value;
}
}
}
}
If possible this would mean turning the set and get values into one unified property called Value
. How do I check if variables inside T
were changed without knowing what T
is? If there is a better way to do this I'd love to know too.
Full Codebase available at: https://gitlab/BitFl1p/udon
INotifyPropertyChanged
on T
The cleanest way is to require T
to implement INotifyPropertyChanged
, which is a standard C# interface for notifying changes.
See bellow code
using System;
using System.ComponentModel;
using UnityEngine;
namespace Udon {
[Serializable]
public class DataReference<T> where T : INotifyPropertyChanged {
[SerializeField] private bool useConstant;
[SerializeField] private DataVariable<T> variable;
[SerializeField] private T constantValue;
private T cachedValue;
public event Action OnValueChanged;
public DataReference()
{
if (!useConstant && variable != null)
{
variable.value.PropertyChanged += HandlePropertyChanged;
}
}
private void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
{
OnValueChanged?.Invoke();
}
public T Value
{
get => useConstant ? constantValue : variable.value;
set
{
if (useConstant)
{
constantValue = value;
}
else
{
if (variable != null)
{
variable.value.PropertyChanged -= HandlePropertyChanged;
variable.value = value;
variable.value.PropertyChanged += HandlePropertyChanged;
}
}
OnValueChanged?.Invoke();
}
}
}
}
T
? Most objects don't have that sort of change detection. For example, imagine it's aList<string>
. That object doesn't raise any sort of event when an item is added or deleted. It has no way to notify another class that it has changed, which means nothing can respond. So that's the first step.T
has to be something that raises events which something else can listen to. – Scott Hannen Commented Apr 1 at 22:48"anything unity can serialize"
, since you cannot determine when changes are made (see first comment, unity can serialize List<string>). You can implement your class variables so they do independent change tracking, but that doesn't seem to be what you're asking. – hijinxbassist Commented Apr 2 at 0:01ReactiveProperty
s .. but currently it's a bit unclear where exactly you want to go with this .... – derHugo Commented Apr 2 at 16:02