Anyway, some of my students were going through the tutorial with 4.9.2 and there’s an issue with one of the User Widget’s going out of scope somehow.
From what I can tell, the SetVisibility function on User Widgets doesn’t actually do anything useful. In the old tutorial I did an Add To Viewport - Remove From Parent pair of calls. Only I think what’s happening with 4.9 is that Remove From Parent is causing the reference count on the UserWidget to go to 0 and the Widget is being cleaned up by the garbage collector.
So I guess my question is… how do I force the GC to ignore this User Widget for collection? In C++ I could grab a pointer that enforces it not being collected. But what about in blueprint? What do you guys do?
The other thing is, does SetVisibility actually work normally? I can’t seem to make it ever show the widget if I change the visibility state at all.
What part of your tutorial are you referring to? That would help a lot in helping you with this.
It sounds like you just need to get the value you want and bind it to a component in your widget. If it’s a value (like in a Text component), to the right of the text inside you can press “Bind” and then bind a value to the function it auto generates. Then you simply have to get the value from whatever you need to read a value from, then convert it to a String and there you go. The game will now constantly show that value whenever the widget calling the function is shown.
Ok, so to explain. I have my menu’s created in GameInstance. I create the “Loading” menu in there. Using CreateWidget and Add To Viewport
When I press a button on my main menu, it is meant to show the Loading screen while it transitions to the map. It does this with Add To Viewport again. First time round in the loop this works fine. I go into the map and exit it again and then if I press play again to load the map, the Loading UI widget is now null.
So basically, the UserWidget reference to my Loading UI widget is being invalidated somewhere. I added a breakpoint to destruct in the UI element itself and its being called sometime after the “remove from parent” is called. Which leads me to believe that removing the widget from its parent is somehow releasing a reference and is essentially making the thing get garbage collected.
So I either need: 1) A way to make sure the reference isn’t GC’d at any point until the GameInstance is OR 2) I need to figure out a way of not using Add To Viewport/RemoveFromParent to do the hide/show if it. Because SetVisibility seems to have no effect.
You can’t use UMG to make a non-streaming loading screen right now. The long and short of it is, a UserWidget, and more specifically Blueprints require a world to work. If you do a non-streamed level load, the persistent level/world go away, and all widgets must go away too, or you get those GC esnures/errors users occasionally report. So we forcefully remove widgets in the viewport if you do a full level load.
Custom load screen currently require you to use use our native slate based loading screen system.
Thanks Nick, that does make sense. But why has that behavior changed? I mean is there a lot of new UI changes in 4.9 that would cause this? Why is the reference for that UI being destroyed? Are all UI’s destroyed before/after world load or something? How is the loading screen even created if it doesn’t have a world initially?
Because it never really worked. A bunch of people tried to make loading screens and kept shooting themselves in the foot, because their loading screen had blueprint code that tried to change some text, or adjust and image…etc, anything that called into blueprints, would cause a crash. So we decided to actively attempt to prevent users from doing it, because it’s just not a good idea with the current state of things.
Yes. We destroy them before a new world, because the engine ensures all things referencing anything outered to the world crashes, because you don’t want actors surviving between worlds, that could go very bad for you. Which is another common crash people see, so we added more code to attempt to prevent those widgets from surviving a level transition.
It does, when you created it there was a world, just before you tried to load the next level. A custom slate loading screen does not require a world. Slate lives far outside of the Actor/World portion of the engine, much lower level.