Due to nature of the way Unity destroys an Entity in ECS versus MonoBehaviours, the EntityStorageInfo property “storage” within FollowerEntity can throw an AssertionException if the GameObject the FollowerEntity script was attached to was already destroyed.
The exact assertion is here, in the specific case of SetDestination being called after Destroy was called on the object. This is only one of several methods that have the same issue. Anytime a script with a reference to the FollowerEntity calls SetDestination, SetPath etcetera, the same frame or later the GameObject was called in Destroy, it will throw something like this. AssertionException: out-of-range indexInArchetype passed to GetChangeVersionArra - Pastebin.com
We have done a thorough investigation and eventually understood a workaround that we implemented in our own codebase and thought it best to let you know you may need to implement it as well.
This exception can get thrown by methods that access storage such as:
SetDestination (line 947 as of 5.1.1)
SetPath (line 1567 as of 5.1.1)
and anything else using an EntityAccess to run its functions.
The workaround considers if the EntityAccess still exists, as when the GameObject is destroyed, if some other script calls to the function, it could be the ECS had already unloaded all of the Components on the Archetype first, even though a reference in some other MonoBehaviour still has FollowerEntity hooked. This allows FollowerEntity to always get index out of range anytime it tries to call a component in the context of the ECS, as the Archetype returned empty. We need to avoid this by checking the components still exist before attempting an access.
Our workaround was to insert a line such as this to make sure the function doesn’t try to call if the component no longer exists on the entity. But we believe your codebase should be able to come up with something more usable than this, and something more knowledgable of object destruction, such as writing your own DestroyThis method instead of letting unity do it, which we recommend, as it seems we’re thread racing ECS at the moment.
if (destinationPointAccessRW.HasComponent(storage))
return;
seemed to work for us but the problem is, this error gets thrown literally anywhere EntityAccess tries to GetComponent at random times, as it seems ECS removes components on a totally different thread. we could choose from any RW at this point, as long as the check for one component of any access aborts before assertion.