I want to subscribe to a value inside a class, but the class can be overwritten at runtime. So I believe I lose the link to the value and the subscriptions no longer get triggered.
So basically when the class changes, I need to rebind the observable to the variable in the new class again in some way.
public class ServiceA : MonoBehaviour {
public ReactiveProperty<ClassA> ClassAInstance = new ReactiveProperty<ClassA>();
public IObservable<ClassA> onClassAChanged => ClassAInstance;
public IObservable<ClassA> onValueInClassAChanged => ClassAInstance.value.SomeVariable;
private void Start() {
onClassAChanged.Subscribe(_ => {
//When ClassAInstance changes, this triggers
//I need to rebind onValueInClassAChanged here somehow
}).AddTo(this);
onValueInClassAChanged.Subscribe(_ => {
//When ClassAInstance changes, this doesn't get triggered anymore when onValueInClassAChanged changes
}).AddTo(this);
ClassAInstance.value = new();
ClassAInstance.value.SomeVariable.value = 5;
}
}
public class ClassA : MonoBehaviour {
public ReactiveProperty<int> SomeVariable = new ReactiveProperty<int>(0);
}
I'm not very familiar with the library you are using. I would strongly recommend to use UniRX. Its name is literally Reactive Extensions for Unity ;)
It offers a lot of handy extension methods and types to deal with this kind of reactive programming.
For that I use an additional extension method which looks like
public static IObservable<TChild1> ToObservableProperty<TRoot, TChild1>(this IObservable<TRoot> observable, Func<TRoot, IObservable<TChild1>> selectChild)
{
return observable.Select(o => o == null ? Observable.Return<TChild1>(default) : selectChild(o)).Switch();
}
which allows to subscribe once and get updated even if the instance itself is changed.
Your classes would rather look like e.g.
public class ServiceA : MonoBehaviour
{
private readonly BehaviourSubject<ClassA> m_CurrentClassA = new (default);
public IObservable<ClassA> CurrentClassA => m_CurrentClassA;
public void UseNewInstane()
{
m_CurrentClassA.OnNext(new ());
}
}
public class ClassA
{
private readonly BehaviourSubject<int> m_Value = new (default);
public IObservable<int> Value => m_Value;
public void SetValue(int newValue)
{
m_Value.OnNext(newValue);
}
}
and a subscriber would rather subscribe to e.g.
private IDispoable subscription;
private void Start()
{
subscription = serviceA.CurrentClassA.ToObservableProperty(c => c.Value).Subscribe(OnAValueChanged);
}
private void OnAValueChanged(int currentAValue)
{
Debug.Log($"Value changed to {currentAValue}");
}
private void OnDestroy()
{
subscription?.Dispose();
}
which will trigger for both, either assigning a new value or using a new instance.
Additionally in UniRX
the target method is also invoke once at the beginning with the current value at the moment Subscribe
is called so you don't miss the init.