Help optimizing logic for AnimInstance/Blueprint

I’ve got a player character set up with functioning animations, and I’m looking to optimize things a bit.

Currently, my animation blueprint reads all its variables from its corresponding AnimInstance class (that way I’m doing as little blueprint logic as possible in the actual animgraph). The AnimInstance class sets all its variables by reading from other classes, like the player character, the player character’s movement component, etc.

To be clear, I’m currently getting those variables in the AnimInstance FROM those other classes, NOT using events IN those other classes to update the variables in AnimInstance. As per Epic’s guidelines here:

As a recommendation, try to not directly access the Anim Instance at all from other classes. Instead, the Anim Instance should pull data from elsewhere.

My problem is that in order to ensure these variables are always updated, without being able to call update functions from other classes, I’m currently setting every one of them on every tick (or rather, on NativeInitializeAnimation() ).

Now, some variables need to be updated every tick to ensure smooth animation, like the player’s speed, direction, and aim offset. Those are just going to stay on NativeInitializeAnimation(). For others, like bJumping (which is being set equal to the player character’s bWasJumping variable from ACharacter on every tick), it was easy enough to simply change out the references in the transition rules in the animgraph to read from ACharacter directly, meaning I can eliminate them from the AnimInstance class entirely.

Where I’m running into problems is with certain other variables, such as bFalling (which is being set to the movement component’s bIsFalling variable every tick). If I try the same approach I tried with bWasJumping and reference bIsFalling directly in the animation blueprint, I get a warning:

Node Result uses potentially thread-unsafe call Get CharacterMovement. Disable threaded update or use a thread-safe call. Function may need BlueprintThreadSafe metadata adding.

Seeing as I don’t want to disable multi-threaded animation logic and I don’t have immediate access to modify that function, I feel like I’m running out of decent options here. Here are the options I’m currently aware of for getting around this problem, please feel free to make any suggestions or let me know if there are other options I’m not aware of:

  • Just leave variables like bWasJumping updating on tick. Quick and easy and I know it’ll work, but also inefficient and I don’t learn how to fix this sort of thing in the future.
  • Disregard Epic’s recommendations and set values in AnimInstance from the player character class. Would give me the advantage of being able to use event-driven logic, but would also create a two-way dependency. And even then I’m still not actually sure how I’d go about setting variables from CharacterMovement without checking every tick (writing a custom extention of the movement component perhaps?)
  • Modify the engine code to add function calls/delegates/whatever to CharacterMovement, ACharacter, and any other class I need to get values from. Probably the most efficient solution and I’m not remotely skittish about touching engine code, but also the greatest amount of work because I haven’t yet set the project up to be able to do that (although I probably should regardless).

Suggestions?

I believe the preferred way if you are using UE5 is to override the new in-built function “BlueprintThreadSafeUpdateAnimation” and use that to Get the values using “Property Access” (BP Safe) that you would previous use the Animation Event Graph. (also remember to make everything possible Fast-Path)

Lyra uses this and while its still doing things every tick at-least its multi-threaded / thread safe, I believe PropertyAccess stores a copy (cache) of the variables via C++ before the BlueprintUpdateAnimation process runs each frame.