sschmid / Entitas

Entitas is a super fast Entity Component System (ECS) Framework specifically made for C# and Unity
MIT License
7.08k stars 1.11k forks source link

New Playmode Options: No Domain Reload vs. Unique Entities & Event Handlers #976

Open thygrrr opened 3 years ago

thygrrr commented 3 years ago

What is the current best practice to use Entitas Teardown() / Contexts.Reset() / ...in conjunction with the new playmode options that are in Unity 2020?

image

The problem is, that unique entities stay alive; as do the handlers for EntityLinks (or specifically, Events that then try to access GameObjects that are Unity null / destroyed)

I have tried to work with Script Execution Order and OnApplicationQuit() on my main controller, but... UnityView components get destroyed befor and after the context is being reset. So either I get the "detected retained entities" issue, or Unity's "trying to access a destroyed GameObject" error.

What kind of seems to work, but feels very hacky, is resetting the contexts on Start():

        private void Start()
        {
            _contexts = Contexts.sharedInstance;
            _contexts.Reset();

and catching the edge case where a UnityViewis destroyed:

        private void OnDestroy()
        {
            //UnityEngine.Debug.Log($"Destroying view {gameObject.name}, linked to {LinkedEntity}");
            if (LinkedEntity != null)
                gameObject.Unlink();
        }

... the latter feels like an inappropriate re-inversion of control, and can have unwanted side effects if something that's not the end of the world Application quit kills the gameobject.

thygrrr commented 3 years ago

To clarify, object destruction order on application termination appears (kind of naturally/obviously) to be largely detached from script execution order, or occurs in several stages! But OnApplicationQuit() is invoked before all of these. You do not get another tick in between, though.

image

mrobaczyk commented 3 years ago

In my project in test's Teardown we do:

roygear commented 3 years ago

Here is my solution :

Add below method to https://github.com/sschmid/Entitas-CSharp/blob/master/Addons/Entitas.CodeGeneration.Plugins/Entitas.CodeGeneration.Plugins/Context/CodeGenerators/ContextsGenerator.cs

    public static Contexts CreateNewInstance()
    {
        _sharedInstance = new Contexts();

        return _sharedInstance ;
    }

Recompile Entitas.CodeGeneration.Plugins

Then call this method before any entitas's call.