Download

Issue using UserWidgets and the Garbage Collection that comes with RemoveFromParent

So in my project I have a UserWidget child class being used like so


 if (UserWidgets[1] != nullptr)
{
   OfficeDepMenuWidget = CreateWidget<UCeoDepMenuWidget>(UGameplayStatics::GetPlayerController(this, 0), UserWidgets[1]);
}

On Actor overlap I then use said defined & created widget, and add it to the viewport like so


void AOfficeDepartment::NotifyActorBeginOverlap(AActor* OtherActor)
{
   if (Cast<AProjectIdleCharacter>(OtherActor) != nullptr)
   {
   if (OfficeDepMenuWidget != nullptr)
   {
   OfficeDepMenuWidget->AddToViewport();
   }
}
}

Well this works, and I remove it like so when no longer in range


void AOfficeDepartment::NotifyActorEndOverlap(AActor* OtherActor)
{
   if (Cast<AProjectIdleCharacter>(OtherActor) != nullptr)
   {
      if (OfficeDepMenuWidget->IsInViewport())
      {
      OfficeDepMenuWidget->RemoveFromViewport();
      }
      else if (BacklogWidget->IsInViewport())
      {
      BacklogWidget->RemoveFromViewport();
      }
   }
}


This also works. Here comes the problem. About a minute later when the garbage collector is triggered (RemoveFromViewport seems to call the GC), the components inside my widget seemed to get deleted as well. If I go inside the overlap again about a minute later, instead of Adding it to the viewport again I crash. (I can go in and out just fine as much as I want before this minute timer runs out before the GC comes to do its stuff)

The widget itself isn’t null, using debug stuff I can see that, it’s instead the components inside the widget that get null’d (Inside the widget blueprint, the components such as the textboxs, horizontal boxes, etc). It’s also pretty clear because in my BeginOverlap which is where I crash, I have a nullptr check.

What gives? I can’t figure out what I’m doing wrong. I need to be able to Show/Hide lots of widgets all the time in this game, and I don’t want to set the visibility of like 30 widgets to hidden if I can get away with removing it instead.

UE 4.24.3

So, I have a few questions for you about your widget setup to see if I can make any suggestions:

  • Are you creating Widget BPs (UMG) and associating C++ classes to them? Or are you building your widgets all in code via Slate?
  • How are you storing your widgets? I see OfficeDepMenuWidget and BacklogWidget in your code snippets, but what are these types? Plain pointers? Shared pointers? What class do they belong to?
  • I’m seeing you indexing into something called UserWidgets – is this a TArray of user widgets? Is this how you’re storing all of your widgets? (haven’t seen this way of doing it before)

It might help to see your .h .cpp for your widget(s) in its entirety to see what’s going on.

Also, Add/Remove from Viewport may not be the best idea to show/hide widgets. You might want to consider looking into something called SWidgetSwitcher which allows showing one of its child widgets at a time (great for menus, for example). May not be exactly what you need in this particular case, but good to keep in mind.

Lemme know and I’ll try my best to help.

[USER=“3467519”]yung drood[/USER] make sure your Widgets variables ( OfficeDepMenuWidget, BacklogWidget ) are UPROPERTY(). I’ve been using AddToViewport and RemoveFromViewport without problem.
If it still doesn’t work, please post the code.