We have a UI transition system to show an animated screen while new levels load when traversing our around game space. When we turn on global invalidation, we end up hitting an ensureAlways in FSlateInvalidationRoot::ProcessAttributeUpdate(), where our InvalidationWidget is null. This seems to persist after the animation is over, it never clears.
After turning on the provided debug options in SlateInvalidationRoot, I am seeing an issue when calling VerifyWidgetList() from ProcessPreUpdate(), saying “The updated list doesn’t match a newly created list”. It dumps the lists it gets from RootWidget and from a call to GetFastPathWidgetList() and sure enough, there are a couple empty elements at the end of the RootWidget list that are not in the newly created list.
I’m not sure how to debug what’s happening here. I have attached the new and updated list files - the two different lines are at the very end. I’m hoping a better understanding of the SlateInvalidationRoot system will help me debug this.
Steps to Reproduce
This is in a custom UI transition system we created to show while loading levels. It isn’t trivial to reproduce in a new project. I’m hoping a better understanding of the Slate Invalidation Root can help me figure out what’s happening.
If it helps - we’ve also encountered this in our game which is on 5.4 too and silenced it.
Hi Philip,
Can you share a bit more about how you’re loading the new level here? Is this a blocking load, seamless travel, etc.? This sounds like it could be vaguely related to Ivan’s post [Content removed] where the invalidation root is lost as part of a level transition. If you see the FStreamingPauseRenderingModule delegate firing as part of the load, it may be worth trying to add that call to InvalidateAllWidgets in EndStreamingPause to see if it helps.
I’d also be curious if you see this in a packaged build or just within PIE. The inconsistency looks to start with STooltipPresenter, and I recall there being a bit of inconsistency between how tooltips are handled in the editor vs. runtime (since we want to host editor tooltips in their own SWindow).
Best,
Cody
Hi Philip,
That delegate is fired as a result of UWorld::BlockTillLevelStreamingCompleted, so it may be triggered at some point here. I’d recommend unregistering it to at least rule that out as a potential cause here:
GEngine->RegisterBeginStreamingPauseRenderingDelegate(nullptr); GEngine->RegisterEndStreamingPauseRenderingDelegate(nullptr);
Best,
Cody
Hi Cody,
Thanks for the reply. We are streaming in sublevels using LevelStreamingDynamic::LoadLevelInstance(). Probably because of that we are not hitting the delegate you mentioned. I’m also seeing this ensure in a Windows packaged build. In the process of the level streaming in we use a material to cover the screen with a full screen transition, and then we wipe our UI and replace it with the appropriate UI for the new level we are showing.
For a bit more tech detail, we are attaching a layout widget to the game viewport, which uses a derivation of CommonActivatablePanel as its base class. The widget has a canvas panel with slots for our UI elements. Each slot is an instance of CommonActivatableWidgetContainerBase, though we only have one widget at a time in them right now.
This main layout widget has the game instance as its parent and is marked to never be destroyed. It is created and attached from a GameInstanceSubsystem on BeginPlay.
Thanks for the reply Cody. We have done some seemingly unrelated refactoring to our screen transfers and I can’t get this ensure to repro anymore. So we must have been doing something to trigger this issue. I appreciate the support!