I am running into an issue with the automation test Project.Maps.PIE after moving from 5.5 to 5.6.
The test is pretty simple, it loads the map, start PIE, wait a bit, stop PIE.
When the PIE is ending, it went over all the objects it can find and mark them as garbage. Call CollectGarbage function, and right after checking if all the objects are freed.
For some reason, one of the maps I have, the GameInstance did not collected by get freed. It just got its internal flag updated from ReachabilityFlag1 to ReachabilityFlag0 or ReachabilityFlag0 to ReachabilityFlag1. Since the test expect the object is freed right after, it failed the test. Interestingly, if I call CollectGarbage twice, it will actually collect it.
There is no change on GameInstance or GC code, resave the map doesn’t fix it. I tried to dig in to see where the flags are being updated, but it seems to be behind the DLLs that I can’t see?
Does anyone know a thing or two on what should I try next to debug this issue? It will be much appreciated!
Weird issue (and possibly wierder description - auto translating? If so include your original language, it could help).
I would suggest creating a new map and moving things over a little at a time to see what - and where introduces the issue.
It could be something like a landscape setting (editable layers style) or just the way the level is set - persistent with multiple tiles in world composition vs world partition. Etc.
Re-creating things in a new level often weeds out issues… and may save you time over trying to figure out the “why" of something that you can’t explain…
I’ve been struggling a bit with the GC system as well. Here are some stuff I had to reconsider:
UObjects will NOT be GC-d as long as there is a pointer to it somewhere. I had to switch over to using TWeakObjectPtr from TObjectPtr in some cases especially for editor modules. Perhaps in other maps you access the game instance somewhere which keeps itt alive for those maps? Although I’m not sure why would you ever want to have the GameInstanceGC-d..
The TObjectIterator class iterates over ALL objects, including ones that are not in the same world as the calling code. From the class’ comments: “Playing In Editor, this will find objects in the editor as well as the PIE world, in an indeterminate order.” I had to put a MyWorld == Object→GetWorld type of code to ensure I don’t touch objects in the editor.
In the editor, if you are using One-File-Per-Actor and World Partition and you do any modification on an actor in the level (e.g. moving it) this actor will NOT be unloaded no matter what you do until you save the level and the dirty status is removed.
Uh…there is no original language, it is just English is not my first language. Sorry if that confuses you.
This map particularly is pretty useful for the workflow as it had catch issues before and is what we are using for running the PIE test. So ideally, I would like to fix it.
The difficulty is that it only started to happen as we upgrade from 5.5 to 5.6. There are some Engine modifications, but I have yet to find any changes that might be related.
Creating a new map does “fix” the issue in the test, but that doesn’t solve the problem.
The GameInstance is GC-d as part of the automation test from Unreal, you can find it under Project.Maps.PIE in fronted session. Create any new Unreal project and the C++ code for this will be under PlayLevel.cpp, UEditorEngine::EndPlayMap().
The map itself is just the template for FirstPersonMap from Unreal, too. I doubt if anyone can replicate this issue since it is probably caused by some engine changes that I am not part of. I was hoping for anyone to know in what situation GC will just flip the flags on an object that is marked as garbage when CollectGarbage is called.
Well the problem is you updated a working project.
In case you don’t know you aren’t really supposed to do that on a working project - ever. It introduces a bunch of bugs and generally doesn’t provide any benefit what so ever since each engine version gets incrementally worse (true over at least the last 4 years).
Likely, the update process “messed up" your level during the update.
I would suggest rolling back if you hopefully kept a working copy.
Other than that - or specifically because of that - the only way you have of fixing it is to re-create the level entierly and move parts over. That is likely to be your “only" possibly fix to the problem.
And it’s not a guarantee that moving over a specific part isn’t going to re-introduce the issue anew… but if it does at least you caught it.
So you should really move over stuff one bit at a time and test in-between to catch anything…
Btw, common practice is to pull an engine version off the git, build it, and use that instead of the launcher so that you can’t even “update" unless you really decide to screw up. (The assumption being when you do want to screw yourself up with an update you have a working copy of before you screw up).
It just got its internal flag updated from ReachabilityFlag1 to ReachabilityFlag0 or ReachabilityFlag0 to ReachabilityFlag1. Since the test expect the object is freed right after, it failed the test. Interestingly, if I call CollectGarbage twice, it will actually collect it.
Would that not be because on first run the flag is changed and on second run the collection can happen?
I believe this was expressly caused by the update process on the asset. Perhaps you can open the umap in an hex editor and fuss with that to make it work again if you want to waste a couple days on it…