VContainer icon indicating copy to clipboard operation
VContainer copied to clipboard

No disposal order?

Open YegorStepanov opened this issue 3 years ago • 3 comments

This looks like incorrect behaviour:

image (Forgot to remove Background/Addressables prefixes on the left picture)

Scope graph is:

Project (Root) ---> Bootstrap ---> Game & Menu

As I see:

  1. Project is always disposed first, but should be last.
  2. Bootstrap should be disposed after it child.
  3. Game and Menu are siblings, it'd be nice to have a deterministic order. They are created one by one with awaiting scene loading:
using(EnqueueParent(bootstrapScope))
{
    var gameScene = await Load();
    var menuScene = await Load();
}
The behaviour should be deterministic and 'child-first'.

YegorStepanov avatar May 11 '22 08:05 YegorStepanov

  1. Project is always disposed first, but should be last.

Agree. This is incorrect.

Question. Is this run on an editor? On the editor, I am running Dispose with playModeStateChanged. https://github.com/hadashiA/VContainer/blob/master/VContainer/Assets/VContainer/Runtime/Unity/VContainerSettings.cs#L75 However, on the actual device, we are not explicitly executing Dispose on the RootLifetimeScope, so it is unlikely that it is executed first.

  1. Game and Menu are siblings, it'd be nice to have a deterministic order.

This depends on how Unity deletes the scene. It is intuitively straightforward for me.

hadashiA avatar May 12 '22 12:05 hadashiA

I deeply apologize for ignoring.

I'll check player behavior today or tomorrow.

YegorStepanov avatar May 25 '22 11:05 YegorStepanov

This depends on how Unity deletes the scene. It is intuitively straightforward for me.

I agree with you. I'm worried about the tree-cache: I have a ScopedAddreessableCache which holds references. If the current cache doesn't contain reference, it checks parent cache. I was worried about some bugs related to the wrong dispose order, but i think it should be fine with current logic.

Editor logic (the same as issue ticket):

  • Root disposed first.
  • Bootstrap, Child1(Game), Child2(Menu) are disposed randomly.

Player logic:

  • Root disposed never
  • The rest are disposed deterministically between build/game launches: Child2(Menu), Bootstrap, Child1(Game).

As I understand, currently Dispose is called in OnDestroy method. It's fine. But it never called for RootScope, because RootScope is not GameObject.

public sealed class TestRootScope : LifetimeScope
{
    protected override void Configure(IContainerBuilder builder)
    {
        builder.RegisterEntryPoint<TestRootEvents>();
    }
    
    protected override void OnDestroy() //not called in Editor and Player
    {
        File.WriteAllText("OnDestroy Root.txt", "...");
        Debug.Log("OnDestroy Root");
        base.OnDestroy();
    }
}

public sealed class TestRootEvents : IInitializable, IDisposable
{
    public void Initialize() { }
    public void Dispose() //called only in Editor. Thanks to EditorApplication.playModeStateChanged
    {
        File.WriteAllText("Dispose Root.txt", "...");
        Debug.Log("Dispose Root");
    }
}

YegorStepanov avatar May 27 '22 13:05 YegorStepanov

Thanks, it's fixed now. Forgot to close

YegorStepanov avatar Aug 24 '22 05:08 YegorStepanov