Cleaning up widgets on travel

I’m having a lot of trouble figuring out the correct way to clean up all of our HUD widgets when travelling to a new map. It’s not clear whether the event is not firing consistently, or Remove From Parent is not performing consistently.

The thing we’re doing currently is hooking the ReceiveDestroyed event on the HUD and calling Remove From Parent on the top level widget, but this just doesn’t seem to happen consistently. The HUD’s EndPlay event seems to be even less reliable.

What’s the best way to just wipe your slate (pun intended) clean? When is the best place to do that to make sure that it always happen when you change maps (taking into account normal transitions, forcible disconnects, returning to the main menu, and anything else I’m not thinking of?

In case it’s not clear, the symptom is that, on the next map, you have some floating element from the previous game mode that just hangs out, unchanging. The reference that would be used to clean it up is then lost, and the only way to get rid of it is to completely kill the client. Is there a “wipe all widgets” method somewhere?

Hello Ryan,

The easiest way to remove all widgets from the view port is to call the base class (User Widget) that all of the other widgets derive from within a “Get all Widgets of Class” node. From there you will want to use a For Each Loop and remove from parent. This will also work for removing any widgets that you may have missed after switching levels. I have provided an example below. I hope that this information helps. If you require further assistance please let me known and I will be more than happy to help.

Example:

Make it a great day

Hello Vince,

I was able to reproduce this issue on our end. I have written up a report ( UE-15885) and I have submitted it to the developers for further consideration. I will provide updates with any pertinent information as it becomes available. Thank you for your information and time. The easiest workaround I have found so far is to create a function library and then to create a function that removes all widgets from the screen (as shown in a previous post). I would then call this function before changing levels. I hope that this helps. If you require any further assistance please let me know and I will be more than happy to help.

Example:

My Function library

My Call

44675-removeallwidgetsfunction2.png

Make it a great day

Hi,

We think this post contains useful information which we would like to share with our public UE4 community. With your approval, we would like to make a copy of this post on the public AnswerHub which includes the discussion but strips out your username and company name. Please let us know if you are okay with this.

Thanks!

Having done a few experiments since I posted the question, the problem seems not to be how, but when. It looks like the Remove From Parent that we were doing in the Destroyed event actually is getting called, but doesn’t seem to work.

I can follow the calls down through:

UUserWidget::RemoveFromParent
UGameViewportClient::RemoveViewportWidgetContent
SOverlay::RemoveSlot

And RemoveSlot does find and remove something, but when we get to the next level, the widget is still there.

Any thoughts?

It does seem like there’s some kind of bug here. At least two things stuck out as odd.

  1. The HUD isn’t destroyed until after the new PlayerController has been created. (If a new one is created during the travel)
  2. Trying to remove a widget during a transition just doesn’t seem to work. And I don’t know why that is. The code is doing everything I would expect for the layers that I understand.

What I ended up doing was putting a RemoveAllViewportWidgets call into PlayerController::PreClientTravel and UEngine::Browse. (My versions of those classes). PreClientTravel is called when server travelling, Browse is called when returning to the main menu.

This definitely doesn’t seem ideal, so if you guys figure out what’s going on here, I’ll be happy to tear it out, but it gets me through the current problem.

  1. 4.7.5
    2/3/4. Will try. I haven’t had great luck creating new projects and making them run, and I’ve never been able to cook/pak/stage two maps at the same time in the editor (required, since the bug requires travelling). Our game has a large build process that wraps UAT, so I’ve never needed to/been able to use the in-editor build process successfully.

If you wanted to try recreating it, it should just be: create a map with a mode with a HUD that has a widget created in the BeginPlay event of the HUD actor. In EndPlay of that HUD, Remove From Parent on the widget. Cook, and travel to another map. Unfortunately, it seems like the bug is timing dependent, so I’m not super-confident that this will repro for you.

Doing it in the level’s BeginPlay event is not really a good solution, since it requires copying the code to each new level we create. Also, when I tried using other BeginPlay events (HUD, PlayerController), they were happening too late, and widgets for the new level had already been created, so attempting to remove everything at that point was destroying widgets I needed to keep. Your assessment of what I’m trying to accomplish is accurate, though.

Hey guys, thought I could help out here.

I’ve been able to repro in the public release of 4.7.6 with the following steps:

  1. Start a new project (I used FPS BP template - named it ‘GrottoPrince’)
  2. Create new mode (GPMode in my example) with a new HUD (GPHud) you’ve made
  3. Make sure Seamless Travel is enabled in that mode
  4. Assign a map to use that new mode (FirstPersonExampleMap)
  5. In that hud (GPHud) at Begin Play assign a user widget (Test) to a variable (see screenshot 1)
  6. In that HUD’s End Play event remove that widget from parent (also in screenshot 1)
  7. Create another mode (for testing - GPMode2)
  8. Make sure Seamless Travel is enabled in that mode
  9. Assign that mode a new hud (GPHud2)
  10. In that HUD’s Begin Play give it a different test widget (Test2)
  11. In that HUD’s End Play event remove the widget from parent (screenshot 2)
  12. Create a new map that uses that mode (TestMap)
  13. Package the game
  14. Server travel between the maps and both of your widgets will still be there when you travel (they don’t get removed from the End Play events in the HUDs) (screenshot 3 - both widgets are displayed)

][1]

Hi Rudy,

Are you sure you’ve enabled Seamless Travel in the game modes that use the HUDs? That seems to be the critical component. If I disable Seamless Travel they get removed as expected when server traveling. If Seamless travel is enabled they stick around. Verified this in the setup you use above (with delay and without the variable).

Ok I went ahead and created a clean project that repros the issue for me. If you build this and server travel between ‘firstpersonexamplemap’ and ‘firstpersonexamplemap2’ you’ll see it redraws the widgets each time (they are set to .25 alpha), and does not remove them (or I’m going crazy perhaps!).

If you disable seamless travel in the game modes the issue does not occur.link text

Hello Ryan,

I have a few questions for you that will help narrow down what issue it is that you are experiencing (in reference to the bug that you mentioned).

Quick questions:

  1. What version of the engine are you using?
  2. Can this issue be reproduced in a clean project?
  3. If so, could you provide a detailed list of steps in order to recreate it on our end( just to make sure we are on the same page and that we are seeing the same issue)?
  4. Could you provide screen shots of any relevant blueprints?

Suggestions for when to clear out your HUD:

From what I understand of your situation and from what I gathered you are trying to accomplish, it seems as though you would like are of your widgets to be gone upon starting the next map/level/lobby. Casting to the player via an event begin play in the level blueprint may be viable.

Hello Vince,

I ran through your reproduction steps. However, this method seems to be working appropriately for me. A way to test if this is the case would be for you to place a delay before you add your widget to the viewport you will see that the widget is being removed and then added back in by the player’s HUD. Could you let me know if this is the case for you?

I went ahead and double checked to make sure that seamless travel was turned on and I made sure to use a fresh project and I went back over the steps provided. However, I the remove from viewport is called and executed every time. The only difference was that I set the text to 50% opacity so that I could tell if the widgets were being stacked on top of each other. Could you check to make sure that your widgets are not getting added to the viewport more than once before being removed?

Yeah, of course.