UMG.AsyncAnimationControlFlow

UMG.AsyncAnimationControlFlow

#Overview

name: UMG.AsyncAnimationControlFlow

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

It is referenced in 7 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of UMG.AsyncAnimationControlFlow is to control whether animation control flow functions (such as Play, Pause, Stop) in Unreal Engine’s UMG (Unreal Motion Graphics) system are performed asynchronously or synchronously.

This setting variable is primarily used in the UMG module, specifically within the animation system of Unreal Engine 5. It affects the behavior of the UMGSequencePlayer class, which is responsible for playing UMG animations.

The value of this variable is set using an FAutoConsoleVariableRef, which means it can be changed at runtime through console commands. By default, it is set to true, enabling asynchronous animation control flow.

The associated variable GAsyncAnimationControlFlow interacts directly with UMG.AsyncAnimationControlFlow. They share the same value, and GAsyncAnimationControlFlow is used in the actual code logic to determine whether to perform certain operations asynchronously.

Developers must be aware that:

  1. This variable affects the performance and behavior of UMG animations.
  2. Changing this variable can impact the timing and responsiveness of animation control functions.
  3. It may have implications for multi-threaded execution of UMG animations.

Best practices when using this variable include:

  1. Consider the performance implications of synchronous vs. asynchronous animation control flow in your specific use case.
  2. Test your UMG animations with both true and false settings to ensure they behave correctly in both scenarios.
  3. Be cautious when changing this value at runtime, as it may affect ongoing animations.

Regarding the associated variable GAsyncAnimationControlFlow:

The purpose of GAsyncAnimationControlFlow is to provide a C++ accessible boolean flag that reflects the value of UMG.AsyncAnimationControlFlow.

This variable is used directly in the UMGSequencePlayer class to determine whether to perform certain operations asynchronously or synchronously. It’s checked in various methods such as UpdateInternal, PlayInternal, Pause, and Stop.

The value of GAsyncAnimationControlFlow is set by the FAutoConsoleVariableRef associated with UMG.AsyncAnimationControlFlow.

Developers should be aware that this variable directly affects the behavior of the UMGSequencePlayer class and, by extension, all UMG animations in their project.

Best practices for using GAsyncAnimationControlFlow include:

  1. Avoid modifying this variable directly in C++ code, as it’s intended to be controlled via the console variable UMG.AsyncAnimationControlFlow.
  2. When debugging UMG animation issues, consider the value of this variable and how it might be affecting animation behavior.
  3. If you need to temporarily force synchronous behavior for debugging purposes, you can set UMG.AsyncAnimationControlFlow to false via console commands rather than modifying the C++ code.

#References in C++ code

#Callsites

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

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

Scope (from outer to inner):

file
namespace    UE::UMG

Source code excerpt:

	bool GAsyncAnimationControlFlow = true;
	FAutoConsoleVariableRef CVarAsyncAnimationControlFlow(
		TEXT("UMG.AsyncAnimationControlFlow"),
		GAsyncAnimationControlFlow,
		TEXT("(Default: true) Whether to perform animation control flow functions (Play, Pause, Stop etc) asynchronously.")
	);

	bool GVarAnimationMarkers = false;
	FAutoConsoleVariableRef CVarAnimationMarkers(

#Associated Variable and Callsites

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

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

Scope (from outer to inner):

file
namespace    UE::UMG

Source code excerpt:

{

	bool GAsyncAnimationControlFlow = true;
	FAutoConsoleVariableRef CVarAsyncAnimationControlFlow(
		TEXT("UMG.AsyncAnimationControlFlow"),
		GAsyncAnimationControlFlow,
		TEXT("(Default: true) Whether to perform animation control flow functions (Play, Pause, Stop etc) asynchronously.")
	);

	bool GVarAnimationMarkers = false;
	FAutoConsoleVariableRef CVarAnimationMarkers(
		TEXT("UMG.AnimationMarkers"),

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

Scope (from outer to inner):

file
function     void UUMGSequencePlayer::UpdateInternal

Source code excerpt:

			Runner->QueueUpdate(Context, RootTemplateInstance.GetRootInstanceHandle(), MoveTemp(OnComplete), UpdateFlags);

			if (Runner == SynchronousRunner || !UE::UMG::GAsyncAnimationControlFlow)
			{
				Runner->Flush();
				ApplyLatentActions();
			}
		}
	}

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

Scope (from outer to inner):

file
function     void UUMGSequencePlayer::PlayInternal

Source code excerpt:

		RunnerToUse->QueueUpdate(Context, RootTemplateInstance.GetRootInstanceHandle(), FSimpleDelegate::CreateWeakLambda(this, OnBegunPlay), UE::MovieScene::ERunnerUpdateFlags::Flush);

		if (RunnerToUse == SynchronousRunner || !UE::UMG::GAsyncAnimationControlFlow)
		{
			RunnerToUse->Flush();
		}
	}
}

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

Scope (from outer to inner):

file
function     void UUMGSequencePlayer::Pause

Source code excerpt:

		RunnerToUpdate->QueueUpdate(Context, RootTemplateInstance.GetRootInstanceHandle(), UE::MovieScene::ERunnerUpdateFlags::Flush);

		if (RunnerToUpdate == SynchronousRunner || !UE::UMG::GAsyncAnimationControlFlow)
		{
			RunnerToUpdate->Flush();
		}
	}
}

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

Scope (from outer to inner):

file
function     void UUMGSequencePlayer::Stop

Source code excerpt:

	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;

	TimeCursorPosition = FFrameTime(0);

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

Scope (from outer to inner):

file
function     void UUMGSequencePlayer::Stop

Source code excerpt:

		Runner->QueueUpdate(Context, RootTemplateInstance.GetRootInstanceHandle(), FSimpleDelegate::CreateUObject(this, &UUMGSequencePlayer::HandleLatentStop), UE::MovieScene::ERunnerUpdateFlags::Flush);

		if (Runner == SynchronousRunner || !UE::UMG::GAsyncAnimationControlFlow)
		{
			Runner->Flush();
		}
	}
}