Correctly handling widget creation and removal

I am working on a mod for Conan Exiles which adds HUD navigation markers in certain situations. For example, when the player dismounts, it will add a marker which points to the location where the player dismounted the horse.

This means, in this situation, I am adding a widget to a canvas dynamically by calling “Create Widget” & “Add Child To Canvas”.

When the player mounts the horse again, I must remove the marker, of course, since it’s no longer valid. I do this by using the “Remove From Parent” function.

Now while this works, it turns out that the removed widget still remains in memory. I noticed this since in order to remove the widget, I am using the function “Get All Widgets Of Class” which also finds the non-visible, already removed ones. Googling for explicit widget destruction seems to unveal that it is not possible to explicitly destroy a widget, and that its not 100% clear if the garbage collector gets rid of it at some point.

I tried to call “Remove From Parent” & directly after “Collect Garbage”. I can see that the garbage collection is actually triggered, because in game I will get a small stutter, but the widget is not destroyed. It will still be found, and after mounting & dismounting the horse several times, I can easily get to the point where about 20 unused (and invisible) widgets are still being iterated during the removal of the (single) currently active marker, which must be removed from parent.

So this leaves me with mixed feelings; 1) there seems to be no way to iterate children of a canvas, so I can’t just skip the already removed widgets. Instead I must always iterate all widgets, 2) I am not sure if garbage collection actually gets rid of the widgets at some point, so after a longer gaming session players might end up with dozens of unsed and invisible widgets, which just does not feel right.

Can I do anything about this, or would this just be the way to go in UE4, and I can’t change it? Will it lead to memory issues actually, or will small widgets (32x32 PNG image) not occupy so much memory so it can be neglected?

When you create a widget, save it to a variable, and use it to RemoveFromParent. There’s no need to Get All Widgets Of Class here.

2 Likes

  1. I am not sure if garbage collection actually gets rid of the widgets at some point

Yes, providing nothing else references the widget.

When the player mounts the horse again, I must remove the marker, of course, since it’s no longer valid. I do this by using the “Remove From Parent” function.

Sounds fine. But how do you know which widget to remove? How do you reference it in the first place after Creating and Adding it to canvas.


There’s no need to Get All Widgets Of Class here.

I believe OP is using it for debugging - to observe how widgets are leaking memory.

If they’re using it to actually find widget(s), then yeah this can lead to things not going all too well.


@Shizai why create / remove the widget? Why not create 1 and then show / hide it only. Much cheaper and no shenanigans with the GC? Which could look like so:

You can, of course, use canvas instead of viewport. Same principle.

Widgets are a massive performance leak if you are recreating them often, like when spamming the MainMenu key to create / remove the main menu. Thing is that we have to create and remove it when desired because both hidden and removed widgets still give the full performance hit including mouse events. The fix seems to be to call the garbage collector right after using RemoveParent and as the others have said garbage collection will only work when there are no property references left.

  • Related

[Bug report] Bad widget performance : Slate : ProcessMouseMove

1 Like

The PNG image won’t actually be in memory multiple times. It’s the same resource, that’s present in the memory only once, and then referenced by the widget.

GC will get rid of unused widgets, but if you call GC in the very same frame, it may not consider the parent-removed widget garbage yet.

Generally, this should be no problem, but if this doesn’t feel right to you, an alternative is simply to create your marker only once, store it in a variable, and when the player mounts the horse, just hide it. When the player unmounts the horse again, update the widget with new information and unhide it again.

I don’t have that function to get canvas children as it seems:

This is why I am iterating all instances of the class. I would prefer to loop only the actual childs of the canvas, and therefore skip the invisble ones, but I could not find any function which allows me to do that.

In regards of hiding instead of removing:
This sounds like a good improvement for the marker which points to the horse location, since there will be only 1 or none. However, the mod will also allow to set arbitrary markers by clicking on the map, and thus there can be many. Implementing some kind of “unused widgets pool” really sounds cumbersome for something which should be handled in a different way, if you ask me?

Do not disable Context Sensitive. Drag a wire first, any panel that can have multiple children handles this:

image

Implementing some kind of “unused widgets pool” really sounds cumbersome for something which should be handled in a different way, if you ask me?

There should never be a need for this in the first place:

image

That’s your widget, use the reference.

Shouldn’t the search reveal all existing functions regardless of context and object when I disable that switch and not drag a wire?

Anyway, I still don’t get it:

I think the issue here is that it’s not a full engine but just a modding SDK of a specific game :confused:

Technically yes but also no :smiley: Not all nodes are available in all contexts → here’s no player controller:

image

And yeah, modding :expressionless: not my area of expertise.


Anyhow, consider refactoring the logic in such a way that you repurpose an existing widget, one that gets created once.

Or improve your referencing game by assigning the value to a variable and then removing its value from the canvas and clearing it afterwards.

Yeah well, as I said, there can be an unknown number of those markers, which I have to add/remove dynamically. Nothing I can know beforehand, or reuse, unless - as mentioned above - I would implement a rather complex logic of reusing invisible but already constructed widgets.

Also I don’t know how referencing widgets in a variable would help; I have no issues finding the widgets, and un-parenting already un-parented widgets is not an issue, so I just ignore the fact that widgets remain accessible.

Okay so long story short:

  1. No way to iterate canvas children means I have to use “Get All Widgets Of Class”

  2. No way of destroying a widget, thus they will reside in memory until garbage collected eventually

  3. I will optimise the marker for the horse to be reusable, the other markers will suffer from accumulating in the background and there’s nothing I can do about it

  4. Hopefully it will not make a big impact, since during game time a player might maybe a have a hand ful of markers, and its done client-side.

I guess I won’t run into any issues here. It just does not “feel” clean :slight_smile:

Add them to an array as or a map (if you have IDs) as you create them - this way they all sit in a container that can be trimmed as needed. Every now & then loop through the array, dereference → Collect Garbage.

Yeah well, as I said, there can be an unknown number of those markers

Pooling is another solution. Although there’d be some upfront work needed first.