AnimInstanceProxy Usage

Reading through the Animation Optimization Guide it says that the AnimInstance should essentially not be used at all anymore and all interaction with the animations should happen through the AnimInstanceProxy. I have some questions that I’d appreciate some input on:

  1. Currently I’m storing all my references to UAnimSequences on my custom AnimInstance (not the proxy) and plugging those variables into Play Animation Sequence nodes inside the states. Is this still fine or should these references also be moved into the Proxy? For some context, using variables for which animations to play makes it easy to create a new Blueprint for different types of melee weapons. E.g. I’ll have a UAnimSequence variable called “IdleAnimLS”, which points to “LongswordIdle” anim asset in my LongswordAnimBP, and points to “IdleAnim1H” in my OneHandSwordAnimBP, and both BPs derive from my MeleeAnimInstance.
  2. What are the rules/best practices around setting the Proxy’s variables from outside? In the Guide, the Proxy is a member of the AnimInstance, so can I for example in my Character class call SkeletalMeshComp’s AnimInstance to get the Proxy, store down a reference to the Proxy and simply update the Proxy during my Character’s tick? Or is there some thread safety issues with doing that? What if I have other classes, e.g. my Controller that also needs to update values stored in the Proxy? I suppose my question is whether the proxy is “standalone” and safe once you got a reference to it through the AnimInstance? Or is there some other way that this must be done while avoiding accessing the AnimInstance?
  3. It looks like you cannot use GetRelevantAnimTimeRemaining/Fraction etc. from Blueprints if you want to ensure FastPath execution. So what’s the alternative? Looking up the times during the Proxy’s Update function and storing them down and then looking up the stored value? Which I suppose leads to the next question.
  4. Can we still use AnimEvents in the Blueprint? E.g. When a state transitions can we still use the State Entered event to set a variable value? E.g. setting bMyWeaponShouldNowStartTracing (member of the AnimProxy) once the attack state is entered, from which the weapon can determine that some code in its tick function should be executed?
  5. How reliable are the warnings generated about calls into the BlueprintVM (AnimBP > Class Settings > Warn About Blueprint Usage)? Will these show every single time a call is made to the BPVM or are there cases it can’t identify which means I could be introducing poor performance unwittingly?
  6. If we cannot use any functions inside the AnimBP for state transitions, do we essentially need to perform all of the transition logic inside the Proxy and reduce it down to pretty much a large collection of calculated bools which determines when the animations can transition between states and then only using those bools in the EventGraph/State Transitions in the Blueprint? This just seems really cumbersome.

In any case, any input would be appreciated. Thanks!

Follow-up: To summarise am I wrong to think that I essentially need to implement a custom state machine from scratch which handles all the transition logic and defines all the states and then instructs the “dumb shell” AnimBlueprint on what to do with straight-forward e.g. “bCanTransitionIntoIdleState” variables?

Bumping this one.

Hey, is there any progress in understanding? Seems like besides the mentioned article and some hardly googlable code fragments the technique stays nearly stillborn. I really don’t understand whether this is something specially connected to custom nodes or must be used anywhere. Assuming the latter, properties inside the proxy are not directly accessible from bp anim graph, so it forces to correct lots of previous works. I’m not sure if it helps in some typical setup just too crowded and slow with no special calculations.

Unfortunately I haven’t made much progress on this. I’m leaning towards the conclusion that C++ support for animations is just not something UE caters for out of the box. I went as far as creating a custom animation queueing system that relies on “AnimInstance->PlaySlotAnimationAsDynamicMontage()”. This seems to work ok but you lose the ability to utilise anything other than basic animations (e.g. you can’t use BlendSpaces).

In short, using AnimBlueprints essentially forces your code to hand over control of the character state to the AnimBP which leaves you to keep querying what’s happening, instead of driving the animation state from code. It makes it really difficult to build complex, dynamic, data-driven character behaviour like GOAP for example.

I suppose you should take everything above with a few bags of salt as I’m not an expert at this by any stretch of the imagination.

As a C++ programmer I wanted to have a full control over animation play on the project I am currently working on.

I created my own derived anim-instance and my own derived anim-instance-proxy. I used UAnimInstance::AddNativeStateEntryBinding to register my callback function which is called whenever a state machine enters a new state (any state). I overrode UAnimInstance::PreUpdateAnimation and FAnimInstanceProxy::PostUpdate to call my own ‘state’ functions. In those, I can check remaining playing time (and therefore initiate a transition into a new state), modify animation replay speed or modify extracted root-motion (in PostUpdate) – it is called on game-thread so it is safe. My AnimBP state machine only uses simple bool/enum/int parameters (exposed in my anim-instance) for blending. Transitions have simple rules, for example like “TargetAnimState != EAnimState::Move” to quit from moving. These parameters are set on game-thread only so there is no problem with animation workers (which are mainly used for animation extraction and blending anyway).

I also implemented a way to pre-process blending-trees in states to extract which blending parameters (and their values) are set. This extraction process creates a table (for every state I need) which stores information about “what must be set to what value” to properly play every animation (= every tree leaf). It is very (very!) handy for synchronizing animation play over network – I just send an index into that table and clients have all the information about which blending parameters to set (to which value) to play a correct animation. Therefore I don’t have any custom animation queuing system (though I admit I was thinking about it in the beginning) as I still use a standard state-machine with states and blending trees inside them.

I think that UE4 animation system (anim-instance) is very well prepared to be used from native C++ code. No need to use any blue-print mambo-jumbo. There are mechanisms which enable us to have a quite a lot of control over how animations are being played. In my project, I also found very handy to be able to implement (or override and modify) blending nodes or sequence player nodes – which I did.

Also note, that animation workers are disabled whenever you enable root-motion extraction in your anim-instance. This is unfortunate. To overcome this, I extract root motion myself in FAnimInstanceProxy::PostUpdate from the most relevant animation, however I do not blend it so there is a limitation. Fortunately, the project I’m working on doesn’t need the root-motion to be blended – there is not much visible impact.

Okay, I’d also code any animation-related math in C++, but anyway Anim BP (and any other visual system) is good for binding resources, so anything meeting “fast path” requirements looks good for me enough to avoid burrying it into C++ code. Once you have custom Anim Inst C++ class, all critical variables in it, NativeUpdateAnimation() to calculate them, even C++ subclassed notifies (though simple event related BPs are hardly so heavy) - you are happy until you read the article “Animation Optimization” that ruins this entire approach.

So if Anim Proxy data is somehow replicated between threads, what happens if this data is accessed from the anim graph (comparing to similar accessing an Anim Inst property) ?

As for Anim Graph state machines, if the logic behind them is generic enough to be useful outside animations, why to use them at all? We can just pass a state enum variable (calculated far deep in the code) to the anim graph and use a blend poses node. Subsequently all state-bound fragments can be made independently in sub anim instances. Are state machines more performance friendly or they allow to expose more information into C++?

Honestly I don’t understand your “that ruins this entire approach” comment. Epic’s document on animation optimization says that: “In general, the UAnimInstance should not be accessed or mutated from within AnimGraph nodes (Update/Evaluate calls) as these can be run on other threads.”
Proxy structure is passed to blending nodes and leaf nodes of the animation tree (Update/Evaluate calls) because these can be executed in parallel. PreUpdate/PostUpdate functions on AnimInstance or AnimInstanceProxy are called from within the game-thread.
Every blending node routinely calls FExposedValueHandled::Execute from its Update_AnyThread where it accesses AnimInstance to update its own exposed properties. It happens all the time. Originally, I thought that proxy somehow makes a copy of all exposed properties from anim-instance (in some pre-update) and FExposedValueHandler accesses these copies so it would be thread-safe. However, I don’t see such code as FExposedValueCopyRecord::GetSourceAddr uses game-instance-object pointer stored in proxy. Just check the source code yourself in a case I am missing something. I guess that Epic wants to say that accessing anim-instance from worker-threads is alright as long as they do not modify it, therefore there are no racing-conditions.

I don’t understand your last paragraph. Are you asking why to use states in AnimBP (state-machines)? When I started working on my current project, my first decision was about how much of the logic will be in AnimBP, how complicated the state machine will be (number of states) – how much I will program it in blue-prints (visual programming). As a C++ programmer I prefer to have the logic done in C++ code because for me personally it is much easier to modify it, test it and fix it. Epic’s optimization document recommends to simplify things and, in general, do not do much of the login in blending trees (or inside transitions) otherwise their scripting virtual-machine is called. It helped me with my decision to use C++ for all the logic and design my animation state-machine just to decomposes all animations into logic “action” blocks. Btw. UE3 didn’t have states – everything was just one single blending tree and it was a nightmare to handle when the project got large.

I don’t know about state-machines performance. Better performance than what? A single blending tree in multiple anim-instances? I’ve never tested anything like that. What Epic’s Unreal engine taught me very early is not to try diverge from the “Unreal way” too much otherwise it will bite you. That’s why I wanted to use their design of states and blending trees as much as possible.

What I meant is to avoid direct using of state machines in anim graph and use something like Blend poses by uenum instead. Why? To get rid of visual mess of transitions (once they overgrow 10 or so states) and to avoid thinking of logic in place where one would think of animation itself. There is hardly a divergence from the “Unreal way” (same set of blending trees, but switched differently), besides the fact that state machines seem more polished then aforementioned blend poses nodes (I found some problems). Okay, I’d once write a separate topic about it.

I had a similar question regarding the migration of member variables, that were formerly in my UAnimInstance for exposure in the Animation Blueprint, to my FAnimInstanceProxy.

I just tried moving all the variables to the proxy and doing all my calculations then setting them in Update(). My proxy was made BlueprintReadAndWrite like it was suggested in the Animation Optimization page and I was able to access the variables through the proxy in the animation blueprint. However, when I connect all the variables after using the node to break the proxy, the editor doesn’t seem to have access to the proxy and throws some kind of error. (I may be wrong here but definitely the variables are being updated and not being read.)

I think keeping the variables that are going to be exposed to animation blueprint should be in the AnimInstance and the proxy should just be used for calculations because they can be done on worker threads. The variables themselves should be copied back to the AnimInstance in the PostUpdate() of the proxy. (I’ll try this asap and report back but I think that’s what should be done.)

Lastly, the suggestion to “try to not directly access the Anim Instance at all from other classes” is there because if you are feeding variables needed for calculations into the proxy from the AnimInstance, there is a chance that other classes could access the AnimInstance variables “while tasks are in-flight” in the worker threads.

So, basically I’m going to be using the proxy for scratch paper :slight_smile:

EDIT: PostUpdate() confirmed working.

Thanks for the explanation, as for me, it made things clearer. By the way, did you investigate how Anim Instance Proxy works for ABP with Sub Anim Instances? Are proxy objects run independently for all sub anim instances or they are somehow shared?

The way I see it, a Sub Anim Instance will use its own proxy by default unless it is coded to use the Main Anim Instance proxy. And although it is possible for all Anim Instances within an AnimBP to use a single proxy, I’m unsure what repercussions there would be. Personally, as of now, I’m planning to use one Anim Instance & proxy per mesh for my project.

I’d like to know how Epic does multi threading and more about multi threading in general but this is way beyond my scope…

@DefCZ thank you very much for sharing all this info - much appreciated!

I’m back on trying to solve this problem again and I think I have a workable approach planned out. Essentially I just have two states in my AnimBP, one to handle movement and implemented purely in Blueprint that handles movement; the other is a dummy state that can perform a bunch of ad-hoc actions generically. Long story short, I need to hook up a delegate to the events you mentioned with AddNativeStateEntryBinding & AddNativeStateExitBinding, but for the life of me can’t figure out how to finally bind the delegate and I would greatly appreciate some help on this. Some background:

In my custom AnimInstance header:

// Delegate for hooking into StateEntered
FOnGraphStateChanged OnActionStateEntryDelegate;

// Function to be bound to delegate for StateEntered - signature looks correct to me
UFUNCTION()
void OnActionStateEntry(FAnimNode_StateMachine& stateMachine, int32 prevStateIndex, int32 nextStateIndex);

In my custom AnimInstance source:

void UPWNAnimInstanceCharacter::NativeBeginPlay()
{
	Super::NativeBeginPlay();

        // Bind function to delegate
        // I've tried this - compiles but the bound function doesn't execute
	OnActionStateEntryDelegate.BindUFunction(this, "OnActionStateEntry");	

        // I've tried this but I can't get it to compile. Looking through examples of BindSP in the source code I can't figure out why this won't compile
	OnActionStateEntryDelegate.BindSP(this, &UPWNAnimInstanceCharacter::OnActionStateEntry);


        // Add delegate to native state entered. I've double checked that the StateMachineName & StateName is correct.
        AddNativeStateEntryBinding(stateMachineName, stateName, OnActionStateEntryDelegate);
}

Some help would be greatly appreciated.

FYI the error I’m getting is:

Building 4 actions with 24
processes… 1> [1/4]
PWNAnimInstanceCharacter.cpp
1>C:\UnrealProjects\TFE\V010\PWNGame\Source\PWNGame\Character\PWNAnimInstanceCharacter.cpp(81):
error C2664: ‘void
TBaseDelegate,const
FAnimNode_StateMachine
&,int32,int32>::BindUObject(UserClass
,void (__cdecl UPWNAnimInstanceCharacter:: )(const
FAnimNode_StateMachine &,int32,int32)
const)’: cannot convert argument 2
from ‘void (__cdecl
UPWNAnimInstanceCharacter::*
)(FAnimNode_StateMachine
&,int32,int32)’ to ‘void (__cdecl
UPWNAnimInstanceCharacter::* )(const
FAnimNode_StateMachine &,int32,int32)’
1> with 1> [ 1>
UserClass=UPWNAnimInstanceCharacter 1>
] 1>
C:\UnrealProjects\TFE\V010\PWNGame\Source\PWNGame\Character\PWNAnimInstanceCharacter.cpp(81):
note: Types pointed to are unrelated;
conversion requires reinterpret_cast,
C-style cast or function-style cast 1>
C:\UnrealEngines\UE_4.24\Engine\Source\Runtime\Core\Public\Delegates/DelegateSignatureImpl.inl(557):
note: see declaration of
‘TBaseDelegate,const
FAnimNode_StateMachine
&,int32,int32>::BindUObject’

I’ve found this post but can’t see what I’m doing wrong. As far as I can tell I’m doing the same thing but it just doesn’t compile.

Continuing with this soliloquy, I’ve found a simple solution to achieve kind of what I need. Basically it boils down to splitting character actions between first-class and dynamic types. E.g. my requirement is to drive multiple basic actions via code. Complicated actions requiring fine-tweaking are implemented as first-class concerns (like movement) in the AnimBP using BP functionality. The rest takes a basic approach with montages driven via code. This is as straight forward as a node to blend by bool between the BP anims and code-driven anims:

I’ve simplified the AnimGraph here to show the core idea. In reality I have multiple AnimActionSlots that apply to different parts of the graph (including full & upper body slots for actions, IK nodes etc.) but the concept remains the same.

The way to get the actions playing on the character is via montage functionality in the AnimInstance code with delegates bound to start, blendout & end events (see [this thread][2]) and passing around custom structs from the animation requester to the AnimInstance. Thread-safety (pushing only from Requester to AnimInstance, never AnimInstance reaching out to Requester) is maintained with a poor man’s implementation using simply two TArrays (actions pending and completed) of AnimAction structs stored on the AnimInstance. Requesters query the completed queue to verify their states.

In any case, I’m happy to share further details if anyone’s interested in this (probably very stupid, but functioning solution). Thanks for everyone’s input, much appreciated. I’m keeping this question open until someone can provide specific answers to the original questions.

Hello,
as I am mainly (99% of time) C++ programmer, my implementations do not use blue-prints but native functions. Therefore I do not bind callbacks to blueprint callable functions declared as UFUNCTION. This is a snippet of code from my current project:

	if ( FBakedAnimationStateMachine const * stateMachineDesc = FAnimInstanceProxy::GetMachineDescription( proxy.GetAnimClassInterface(), stateMachine ) )
	{
		auto StateEntryCallback = FOnGraphStateChanged::CreateUObject( this, &USFLCharacterAnimInstance::OnEnterState );
		for ( FBakedAnimationState const & state : stateMachineDesc->States )
		{
			// Following is currently the only way how to register a notification callback for state change.
			AddNativeStateEntryBinding( MainStateMachine, state.StateName, StateEntryCallback );
		}
	}

As you see, I use FOnGraphStateChanged::CreateUObject to create a callback to my native function which is declared as void OnEnterState( struct FAnimNode_StateMachine const & Machine, int32 PrevStateIndex, int32 NextStateIndex ).
Since you want to bind to UFUNCTION, you probably should use delegate’s CreateUFunction version.

On that error you posted, I see it reports that your function declaration is not compatible with callable type. Delegate wants to call a function which has the first parameter declared as a reference to const(!) object. Your function has a reference to non-const object.

I can’t comment much on your solution as we do not use montages in our current project at all. I found them rather tedious to work with as animators need to create an animation first and then prepare a montage. Too much hassle. What is their advantage over standard UAnimSequence? Control? If I need to play some special animation (specified outside of the animation system), I just take that passed reference to UAnimSequence asset and put it into a FAnimNode_SequencePlayer node in my blending-tree. I do it on game-thread (there are many entry points where it can be safely done). I play it in an animation-state dedicated especially for that. In that state, I detect when animation play ends and quit the state.
Of course, the best solution is always that which suits your needs and coding styles the most.

I don’t understand your comment on thread-safety using two arrays for passing some parameters. Most probably I just don’t follow your intentions as I don’t know your project. I always thought that as long as I prepare all necessary data (parameters) for AnimInstance (and AnimInstanceProxy and animtree nodes) on game-thread and do not modify them when worker-threads are active, I will be fine and no racing-conditions happen. So far it works for me. However maybe I am wrong and there is some problem lurking behind the corner? Also, please note that I do not use blueprint scripts in my animation instance (except one, not created by me, which controls blending of additive animations for running character to lean when turning – and it is executed on game-thread).

Ah ok thanks - that was really stupid of me missing the const.

Using arrays serve two purposes for me:

  1. Queuing animations/actions
  2. Thread safety
  1. I need to queue animations in some circumstances, mainly for player & AI combat behaviour to ensure that decisions/instructions made while one action is still in progress gets executed as soon as it can. For example, a block request comes in while an attack animation is still playing. Instantly switching from one to the other won’t respect the abilities/combat rules and can cause animation artefacts. I also don’t want the player/AI to spam an action request until it’s ready to execute. So I queue them up and when the current action reaches some progress percentage where it’s deemed interruptable, the queuing system takes care of executing the next action. I don’t literally use montages - I use AnimSequences (along with some other data all stored in a struct) and play them as montages with “PlaySlotAnimationAsDynamicMontage”. So no need for animators/artists to convert animations to actual montages.

  2. This might actually not be relevant anymore - quite some time ago I ran into some thread-safety issues when mutating the AnimInstance state from outside and at the same time pulling data from e.g. the Character during the AnimInstance updates. I must admit I’m not sure whether this is still required, however I haven’t run into the issue again since using this approach.