Widget.UseParallelAnimation

Widget.UseParallelAnimation

#Overview

name: Widget.UseParallelAnimation

This variable is created as a Console Variable (cvar).

It is referenced in 10 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of Widget.UseParallelAnimation is to control whether widget animations in Unreal Engine 5 are evaluated using multi-threaded processing. This setting is primarily used for optimizing the performance of the UMG (Unreal Motion Graphics) system, which is responsible for creating and managing user interfaces in Unreal Engine.

This setting variable is mainly relied upon by the UMG module, specifically within the animation subsystem of UMG. It affects the behavior of classes such as UUserWidget, UUMGSequencePlayer, and UUMGSequenceTickManager.

The value of this variable is set through a console variable (CVar) named CVarUserWidgetUseParallelAnimation. By default, it is set to true, enabling multi-threaded evaluation for widget animations.

The associated variable CVarUserWidgetUseParallelAnimation interacts directly with Widget.UseParallelAnimation. They share the same value and are used interchangeably in the code.

Developers must be aware that:

  1. Enabling this variable (set to true) allows for multi-threaded evaluation of widget animations, which can improve performance, especially in scenarios with many animated widgets.
  2. Disabling this variable (set to false) will cause animations to be evaluated on the main thread, which might be necessary for certain debugging scenarios or if there are synchronization issues.
  3. The setting affects various aspects of widget animation, including stopping animations, queueing latent actions, and the overall ticking process of widget animations.

Best practices when using this variable include:

  1. Generally, leave it enabled (true) for better performance in most cases.
  2. If experiencing issues with widget animations, particularly related to timing or synchronization, try disabling it temporarily for debugging.
  3. Be cautious when modifying this setting at runtime, as it can affect the behavior of all widget animations in the game.
  4. When implementing custom widget animation systems, consider checking this variable to ensure compatibility with the engine’s parallel animation system.

Regarding the associated variable CVarUserWidgetUseParallelAnimation: This is the actual console variable that controls the Widget.UseParallelAnimation setting. It is defined in the UMG module and is used throughout the widget animation system to determine whether parallel animation evaluation should be used. The same considerations and best practices apply to this variable as they do to Widget.UseParallelAnimation.

#References in C++ code

#Callsites

This variable is referenced in the following C++ source code:

#Loc: <Workspace>/Engine/Source/Runtime/UMG/Private/UserWidget.cpp:43

Scope: file

Source code excerpt:


TAutoConsoleVariable<bool> CVarUserWidgetUseParallelAnimation(
	TEXT("Widget.UseParallelAnimation"),
	true,
	TEXT("Use multi-threaded evaluation for widget animations."),
	ECVF_Default
);

uint32 UUserWidget::bInitializingFromWidgetTree = 0;

#Associated Variable and Callsites

This variable is associated with another variable named CVarUserWidgetUseParallelAnimation. They share the same value. See the following C++ source code.

#Loc: <Workspace>/Engine/Source/Runtime/UMG/Private/Animation/UMGSequencePlayer.cpp:13

Scope: file

Source code excerpt:

#include UE_INLINE_GENERATED_CPP_BY_NAME(UMGSequencePlayer)

extern TAutoConsoleVariable<bool> CVarUserWidgetUseParallelAnimation;

namespace UE::UMG
{

	bool GAsyncAnimationControlFlow = true;
	FAutoConsoleVariableRef CVarAsyncAnimationControlFlow(

#Loc: <Workspace>/Engine/Source/Runtime/UMG/Private/Animation/UMGSequencePlayer.cpp:380

Scope (from outer to inner):

file
function     void UUMGSequencePlayer::Stop

Source code excerpt:


	UMovieSceneSequence* MovieSceneSequence = RootTemplateInstance.GetSequence(MovieSceneSequenceID::Root);
	const bool bIsRunningWithTickManager = CVarUserWidgetUseParallelAnimation.GetValueOnGameThread();
	const bool bIsSequenceBlocking = EnumHasAnyFlags(MovieSceneSequence->GetFlags(), EMovieSceneSequenceFlags::BlockingEvaluation);
	const bool bIsAsync = bIsRunningWithTickManager && !bIsSequenceBlocking && UE::UMG::GAsyncAnimationControlFlow == true;

	UUserWidget* Widget = UserWidget.Get();
	UUMGSequenceTickManager* TickManager = Widget ? ToRawPtr(Widget->AnimationTickManager) : nullptr;

#Loc: <Workspace>/Engine/Source/Runtime/UMG/Private/Animation/UMGSequencePlayer.cpp:514

Scope (from outer to inner):

file
function     void UUMGSequencePlayer::QueueLatentAction

Source code excerpt:

void UUMGSequencePlayer::QueueLatentAction(FMovieSceneSequenceLatentActionDelegate Delegate)
{
	if (CVarUserWidgetUseParallelAnimation.GetValueOnGameThread())
	{
		UUserWidget* Widget = UserWidget.Get();
		UUMGSequenceTickManager* TickManager = Widget ? ToRawPtr(Widget->AnimationTickManager) : nullptr;

		if (ensure(TickManager))
		{

#Loc: <Workspace>/Engine/Source/Runtime/UMG/Private/Animation/UMGSequencePlayer.cpp:532

Scope (from outer to inner):

file
function     void UUMGSequencePlayer::ApplyLatentActions

Source code excerpt:

void UUMGSequencePlayer::ApplyLatentActions()
{
	if (CVarUserWidgetUseParallelAnimation.GetValueOnGameThread())
	{
		UUserWidget* Widget = UserWidget.Get();
		UUMGSequenceTickManager* TickManager = Widget ? ToRawPtr(Widget->AnimationTickManager) : nullptr;
		if (TickManager)
		{
			TickManager->RunLatentActions();

#Loc: <Workspace>/Engine/Source/Runtime/UMG/Private/Animation/UMGSequencePlayer.cpp:586

Scope (from outer to inner):

file
function     void UUMGSequencePlayer::BeginDestroy

Source code excerpt:


	// Remove any latent actions added by this player.
	if (CVarUserWidgetUseParallelAnimation.GetValueOnGameThread())
	{
		UUserWidget* Widget = UserWidget.Get();
		UUMGSequenceTickManager* TickManager = Widget ? ToRawPtr(Widget->AnimationTickManager) : nullptr;
		if (TickManager)
		{
			TickManager->ClearLatentActions(this);

#Loc: <Workspace>/Engine/Source/Runtime/UMG/Private/Animation/UMGSequenceTickManager.cpp:40

Scope: file

Source code excerpt:

} // namespace UE::UMG

extern TAutoConsoleVariable<bool> CVarUserWidgetUseParallelAnimation;

UUMGSequenceTickManager::UUMGSequenceTickManager(const FObjectInitializer& Init)
	: Super(Init)
	, bIsTicking(false)
{
	if (!HasAnyFlags(RF_ClassDefaultObject))

#Loc: <Workspace>/Engine/Source/Runtime/UMG/Private/Animation/UMGSequenceTickManager.cpp:107

Scope (from outer to inner):

file
function     void UUMGSequenceTickManager::TickWidgetAnimations

Source code excerpt:

void UUMGSequenceTickManager::TickWidgetAnimations(float DeltaSeconds)
{
	if (!CVarUserWidgetUseParallelAnimation.GetValueOnGameThread())
	{
		return;
	}

	if (bIsTicking)
	{

#Loc: <Workspace>/Engine/Source/Runtime/UMG/Private/UserWidget.cpp:42

Scope: file

Source code excerpt:

#define LOCTEXT_NAMESPACE "UMG"

TAutoConsoleVariable<bool> CVarUserWidgetUseParallelAnimation(
	TEXT("Widget.UseParallelAnimation"),
	true,
	TEXT("Use multi-threaded evaluation for widget animations."),
	ECVF_Default
);

#Loc: <Workspace>/Engine/Source/Runtime/UMG/Private/UserWidget.cpp:1810

Scope (from outer to inner):

file
function     void UUserWidget::NativeTick

Source code excerpt:

			}

			if (!CVarUserWidgetUseParallelAnimation.GetValueOnGameThread())
			{
				TickActionsAndAnimation(InDeltaTime);
				PostTickActionsAndAnimation(InDeltaTime);
			}
			// else: the TickManager object will tick all animations at once.