mattak / Unidux

Redux Architecture for Unity 🎩
MIT License
386 stars 27 forks source link

How to unsubscribe? #125

Closed ameliemaia closed 5 years ago

ameliemaia commented 6 years ago

First of all, thanks for this project. I'm finding it very useful! I have a situation where a game object has been destroyed but the subscription is still active. I've tried the following:

storeObserver = Unidux.Subject
                .TakeUntilDisable(this)
                .StartWith(Unidux.State)
                .Subscribe(onSubscribed)
                .AddTo(this);

and then:

    public void OnDestroy() {
            Debug.Log("destroy");
            storeObserver.Dispose();
        }

But I still receive updates. I'm concerned with GC, whats the best way to completely unsubscribe in OnDestroy?

ameliemaia commented 6 years ago

I also just tried TakeUntilDestroy and I still receive updates after OnDestroy is called.

mattak commented 6 years ago

Hi, @amelierosser .

Thanks for using Unidux! I'm very glad to hear uservoice.

It looks your code successfully unsubscribe Unidux.Subject, if you destroy gameobject. Dispose() works in ObservableDestroyTrigger#OnDestroy. The script will be added automatically when you call AddTo function. You can check ObservableDestroyTrigger on your inspector when the application is running as followings.

2018-02-24 10 45 41 pm

I created a small example of checking AddTo(this) function and it works well.

public class Renderer : MonoBehaviour
{
    void Start()
    {
        Unidux.Subject
            .Subscribe(state => Debug.LogFormat("Subscribe: {0}", state.Count))
            .AddTo(this);
    }

    void OnDestroy()
    {
        Debug.Log("OnDestroy");
    }
}

destroycheck

Could you show me the detail of your codes, or small reproducible codes?

I think there are problems at the other part of codes. For example, you added your subscribe script to multiple game objects and some game objects are not destroyed (e.g. object-A is destroyed, but object-B is still alive).

ameliemaia commented 6 years ago

Hey @mattak, thanks for your detailed answer. The problem still persists. As you can see in the screenshot attached I'm still receiving an update from the store even when the destroy method has been called. I can add a boolean to return once onDestroy() has been called but it's hacky. Can you recommend anything else?

screen shot 2018-02-27 at 17 41 15
mattak commented 6 years ago

Hi, @amelierosser.

Thanks for your screenshot.

Questions

Where is the message Tutorial::propsChanged: experianceMode: ... placed in? Is it in your OnSubscribe function? If so, try the next suggestions. If not so, I might have made the wrong suggestion.

Suggestions

I recommend you to use .Debug("DEBUG:" + this.GetInstanceID()) method. It will help you to debug UniRx subscription behaviour. I wrote an example as following.

using UniRx;
using UniRx.Diagnostics;
using UnityEngine;

namespace Unidux.Example.DestroyCheck
{
    public class Renderer : MonoBehaviour
    {
        void Start()
        {
            Unidux.Subject
                .Debug("DEBUG: " + this.GetInstanceID())
                .Subscribe(this.OnSubscribe)
                .AddTo(this);
        }

        void OnSubscribe(State state)
        {
            Debug.LogFormat("Subscribe: {0}", state.Count);
        }

        void OnDestroy()
        {
            Debug.Log("OnDestroy");
        }
    }
}

example

When you subscribe, [DEBUG: xxxx]OnSubscribe message will be logged. When you dispatch something, [DEBUG: 11456]OnNext() message will be logged. When you destroy object, [DEBUG: xxxx]OnCancel message will be logged.

Expected log orders are OnSubscribe (=> OnNext)* => OnCancel. Is there any OnNext message appeared even if you see OnCancel message? If so there might be some other subscription object. Then please check instance id of [DEBUG: <instance id>] to find which object will still subscribe.

mattak commented 5 years ago

It's not responding