PIE Access violation with UUserWidget

Hi I get an access violation when I remove an UserWidget from the viewport during ending PIE.

void ATestPawn::PossessedBy(AController* NewController)
{
	APlayerController* const Player = Cast<APlayerController>(NewController);

	if (Player)
	{
		Widget = CreateWidget<UUserWidget>(GetWorld(), WidgetClass);
		Widget->AddToViewport();
	}
	
	Super::PossessedBy(NewController);
}

void ATestPawn::UnPossessed()
{
	Super::UnPossessed();

	if (Widget != nullptr)
	{
		Widget->RemoveFromViewport(); <- exception 
		Widget = nullptr; 
	}
}

During gamplay it is working as intended but if the PIE session is closed an exception is thowen in UnPossessed()

I am running into a similar issue.

I suspect this to be a twofold issue. UserWidget::RemoveFromViewport() calls GetViewportWidget() on a nulltpr returned from GetGameViewport() - see code below. So there should probably a nullptr-check before doing so.

However the real problem is that ending a PIE session seems to remove that GameViewport too early, since clearly the Game must be able to shut down its widgets in the same way regardless of the reason why the owning Actor has been shut down.

A workaround is to do that nullptr-check before calling RemoveFromViewport() and not remove the widget if the pointer is null. The Garbage Collection should take care of the problem but that is really bad style.

Marc

Code:

void UUserWidget::RemoveFromViewport()
{
	if ( FullScreenWidget.IsValid() )
	{
		TSharedPtr<SWidget> RootWidget = FullScreenWidget.Pin();

		// If this is a game world add the widget to the current worlds viewport.
		UWorld* World = GetWorld();
		if ( World && World->IsGameWorld() )
		{
			UGameViewportClient* Viewport = World->GetGameViewport();
			Viewport->RemoveViewportWidgetContent(RootWidget.ToSharedRef());

			TWeakPtr<SViewport> GameViewportWidget = Viewport->GetGameViewport()->GetViewportWidget();
			if ( GameViewportWidget.IsValid() )
			{
				//TODO UMG this isn't what should manage focus, a higher level window controller, probably the viewport needs to understand
				// the Widget stack, and the dialog stack.
				GameViewportWidget.Pin()->ClearWidgetToFocusOnActivate();
				FSlateApplication::Get().SetKeyboardFocus(TSharedPtr<SWidget>());
			}
		}
	}
}