[Bug] RecastMeshObject errors on scene destruction, breaks on second scene load


#1

RecastMeshObj works really poorly with scene unloading and loading. The context of this happening for me right now is that I’m exiting to the game’s main menu, and then entering the scene with the RecastMeshObjects again later.

  • When unloading a scene with them in, either due to quitting play mode, or loading a different scene, all of the RMOs that are static throws an exception complaining that they can’t be removed from the tree.
  • When you load the scene again, all of the RMOs that are static causes exceptions to be thrown in RecastBBTree.Insert, in this line:
    float e1 = ExpansionRequired(c.c1.rect, box.rect);

This is because RecastMeshObj.tree is kept around, so it has data about the now unloaded scene.

I made a “fix”, but it’s really ugly:

	private static bool ignoreFailedRemoves;
	private void OnApplicationQuit() {
		ignoreFailedRemoves = true;
	}

	public static bool LoadingScene {
		set {
			ignoreFailedRemoves = value;
			if(value)
				tree = new RecastBBTree();
		}
	}

	void OnDisable () {
		registered = false;

		if (_dynamic) {
			dynamicMeshObjs.Remove(this);
		} else {
			if (!tree.Remove(this) && !ignoreFailedRemoves) {
				throw new System.Exception("Could not remove RecastMeshObj from tree even though it should exist in it. Has the object moved without being marked as dynamic?");
			}
		}
		_dynamic = dynamic;
	}
}

Then, loading my main menu becomes:

RecastMeshObj.LoadingScene = true;
yield return SceneManager.LoadSceneAsync(0);
RecastMeshObj.LoadingScene = false;

Which works, but is really painful, and I’ve got a sinking feeling that there’s probably more static caches of data somewhere in A* that also needs to be cleared out.

I’m not quite sure how RecastMeshObjects should handle all of this, but there’s a lot of issues around scene loading that will pop up. Multi-scene editing also throws a wrench into all of this.
As an alternative, maybe A* should have a static “ClearAllData” method we can call to notify it that none of it’s cached data is valid anymore.


#2

Hi

Are your RecastMeshObj components marked as dynamic? If not, try marking them as such (I think that is the default too). As the error message says, you cannot move RecastMeshObj components unless they are marked as dynamic. I do agree that it should probably handle the failure more gracefully though.