Hi,
How can I destroy UMG widget? If I call “Remove from Parent” it stil exists in memory…
Unfortunately, it cannot be done. There’s no destruction call in UMG. Once you reference it, it remains in the memory.
You can either make it invisible/collapse it or remove it from the parent…
Wouldn’t garbage collection eventually take care of it, if you set any references to the widget in question to NULL (or equivalent)?
Just a thought, haven’t tested it.
Once all references are gone, the GC should ‘eventually’ kick in :>
So will it impact performance a lot if I create a lot of widget and only remove them from parent?Thanks!
I am not sure how that will affect performance but you could create a widget at begin play or construct events, store the reference in a variable and use that to add/remove the widget. This way you avoid that potential problem.
You can avoid creating lots of widgets by testing to see if a widget of the class that you want already exists. If it does exist already then display it and if it doesn’t exist then create it.
The Widget that I am going to display in this example is called widget_midi_test and is being called from another widget hence the Remove from parent (self) at the end.
The compiler will tell you that the cast is not necessary - see the note on the node. But the failed cast tells you that it does not exist. It works for me anyway and has the advantage of also retaining the value of any variables stored in that widget. fjellgnus’ reference method above probably does much the same but does not tell you if one already exists.
cheers
Here is my solution:
https://forums.unrealengine.com/community/community-content-tools-and-tutorials/1392662-tool-widgetbox-recycle-your-widgets-the-smart-way
I do not understand why you’d ever want to do all that. Widgets are garbage collected just fine, are they not? You dereference it and it goes away - that’s my experience at least.
Could you describe a scenario in which what you’re suggesting is efficient in the slightest. Perhaps you’ve run some tests?
You have a delay in Tick and then iterate through 100 elements. How is that saving performance.
It is called example. You could have for e.g. an ingame folder browser. On every folder click you need to repopulate the folder structure. There you would need much widgets.
If I call GetAllWidgetsOfClass I can’t for real see garbage collection. Even calling uppon CollectGarbage does NOT pickup the widgets that were removed from parent (No, the widgets are not stored in an array)
Edit: I for once had a debug interface where I put in a text widget for every debug message that was printing with timeout that removes them from the parent. I had lots of widgets going and after some time I had huge performance issues.
Hi,
I’m pretty surprise to see that. I built some UI for my game and I didn’t see any performance hit in any case.
If you have a repro project, I suggest you to raise a Bug request and send them the repro project.
It is said that when the widget is removed from parent, it should be garbagged. If it is not the case, it is a bug.
This would solve the issue for everyone without any extra stuff.
Thanks,
I’d have to agree with Elvince here. I’ve worked with inventories with up to 1500 widgets in a single container, occasional more than one of those and apart from typical UMG quirks, I’ve never experienced anything that made me consider object pooling.
There are already some Post around the forum/answerhub regarding widget and destruction/garbagecollection and it seemed non did care.
Somewhere I also read that the Widget guru Nick Darnell mentioned you should reuse widgets as possible as creating the slate ressource for the widget is quite expensive.
What ever, here you go: Thread
@Rumbleball: I’m afraid you’re creating utter chaos by delaying the tick node. I mentioned it before. Please consider the following:
- create 100 widgets
- add them to both the viewport and an array
- remove them from viewport and the array
- it prints 0, as expected
Somewhere I also read that the Widget
guru Nick Darnell mentioned you should
reuse widgets as possible as creating
the slate ressource for the widget is
quite expensive.
And I could not agree more but what you’re suggesting seems to me a like a pretty bad application of the method. Check whether the widget already exists, if it does not - create it.
Perhaps you were referring to [this comment][2] - but it seems to confirm what I mentioned above. Do correct me if I’m wrong, though. Here’s a confirmation from Rudy, too:
On the other hand, I’d be happy to follow your thread, perhaps you’ve discovered something truly dodgy. I know for a fact that GC is far from perfect (although it was made much faster in 4.17 according to the patch notes) and the memory footprint does not always reflect how GC is expected to work.
1: Thanks for the discussion. Someone will be smarter in the end.
2: If the tick is the issue: THEN we have a real problem.
3: As the comment on the delay says, it is needed to get visuals. It does not work when executed with tick only, for what ever reason. If the Delay is the issue: THEN we have a another real problem.
Tick and Delay are just sources of execution. If I use those or a button press should not matter at all. Well, you could mess things up when having a split execution path, like tick populates the widget and tick+delay removes the widgets from the parent. But even that removes the widgets from the parent and would only be a visual chaos.
3: Gave your code a try and yes, it SEEMED it worked. So whats the difference? You add it to viewport + array, I just add it as child to another widget. Well, tried your code at BeginPlay but added it to my parent widget instead of viewport. It again SEEMED to work. But then I noticed you have GetAllWidgetsOfClass::TopLevelOnly checked. Uncheck that and there you go. It does NOT work (Have a tick print GetAllWidgetsOfClass).
It also would have been quite strange if your code worked for real as you remove the widgets and read the widget count in the same engine cycle. “Widgets are garbage collected” but you did not gave the garbage collection time to pick it up.
Edit: Try console command “obj gc” to force garbage collection. Does not work either.
Be careful with
GetAllActorOfClass
…Try to not use this node anymore because it need a very large performance consumption.
Edit Aug 4, 2020
Thanks to @everyone’s comment. RemoveFromParent can make it garbage collected, even though the widget created by CreateWidget node is always owned by the player controller, which was observed by me and was mentioned by the Staff’s reply in Widget component widget not garbage collected - UI - Epic Developer Community Forums
By the way, I met a similar problem these days that UMG widget was left on the screen. I thought it were the same issue, but after debugging I found it was produced by another bug, not a gc problem.
edit: It was not working (correctly) once uppon a time. Now they get destroyed happily ever after. The End