Search code examples
unity-game-enginereactive-programmingunirx

Is it possible to make RactiveProperty public get private set in UniRx


I have two classes. One of them have BoolReactiveProperty. I want the second class to be able to subscribe only without being able to change the value. This is my current code

public class SourceToggle : MonoBehaviour
{
    public BoolReactiveProperty boolRP { get; private set; } 
        = new BoolReactiveProperty();

    private void Start()
    {
        boolRP.Subscribe(b => GetComponent<Toggle>().isOn = b);

        GetComponent<Toggle>()
            .OnValueChangedAsObservable()
            .Subscribe(b => boolRP.SetValueAndForceNotify(b));
    }
}

public class SubscribedToggle : MonoBehaviour
{
    [SerializeField]
    private SourceToggle sourceToggle;

    private void Start()
    {
        sourceToggle.boolRP
            .Subscribe(b => GetComponent<Toggle>().isOn = b);

        GetComponent<Toggle>()
            .OnValueChangedAsObservable()
            .Subscribe(b => sourceToggle.boolRP.SetValueAndForceNotify(b));
    }
}

Solution

  • I don't totally get what you want to prevent. I guess you want to prevent your SubscribedToggle to call SetValueAndForceNotify on your ReactiveProperty?

    Then declare a public IReadOnlyReactiveProperty and manage a private BoolReactiveProperty in your SourceToggle class.

    public class SourceToggle : MonoBehaviour
    {
        private BoolReactiveProperty isOn;
        private Toggle toggle;
    
        public IReadOnlyReactiveProperty<bool> IsOn => isOn;
    
        private void Awake()
        {
            toggle = GetComponent<Toggle>();
    
            isOn = new BoolReactiveProperty(toggle.isOn);
    
            toggle
                .OnValueChangedAsObservable()
                .Subscribe(b => isOn.SetValueAndForceNotify(b));
    
            isOn.Subscribe(b => toggle.isOn = b);
        }
    }
    
    public class SubscribedToggle : MonoBehaviour
    {
        [SerializeField]
        private SourceToggle sourceToggle;
    
        private void Start()
        {
            sourceToggle.IsOn
                .Subscribe(b => GetComponent<Toggle>().isOn = b);
    
            // GetComponent<Toggle>()
            //     .OnValueChangedAsObservable()
            //     .Subscribe(b => sourceToggle.IsOn.SetValueAndForceNotify(b)); // Impossible to call SetValueAndForceNotify
        }
    }