Should we avoid Non Threadsafe Update Anim Blueprint?

There are cases where it’s harder to use property access nodes and I’m trying to figure out if it’s worth the trouble.

For example, property access nodes themselves are still under the hood, taking the data on the game thread, and caching it.

So for something simple like velocity = characterMovement->getVelocity(), what’s the benefit of doing that in the threadsafe update using property access instead of just doing that in the regular non threadsafe blueprint update function? Is it really that much faster if property access is still caching it on the game thread earlier?

I’m also considering, should I mix regular update and threadsafe update? Like if I have a chance to put as much of my update code in the threadsafe update, but then if there’s like 1 thing that needs to go into the regular non threadsafe update, am I losing the benefits? Or are we supposed to mix them when we need to?

I have one function that takes a parameter, so it can’t be used in property access. And I’m trying to figure out, is it worth me adding a getter for that one specific thing that doesn’t take the parameter just so I can actually use property access or is it just doing the same thing underneath anyway even if I use property access, and I just added weird apis to my beautiful clean code?

General rule of thumb is you never get, you use pre-filled variables instead.

So in the character realm (since that is the forum you posted in) you make a character class, add all the variables you want and expose them, then set them to update or fill in.

From them on, everything else (like the animation blueprint) accesses said variable directly.

No re-mirroring and re-setting needed as it takes more effort and compute to transfer than to read.

With that, some vars are pre-filled by the original class you modify. Location, tranform, velocity etc. So you can and should access them directly.

The only real concern with characters is the fact your ABP has to have 0 code and you need to make sure you aren’t negating fastpath by complicating transitions with non fastpath accessible checks.

Because of that, it’s often better to create variables in the ABP and force the character to update the ABP variables directly. So Maybe velocity, location, etc is something you expose in ABP, update from character, and consume directly.

Make sense?

Also. Velocity is directly tied to input realistically. So if you are concerned about threads and having to set it, you can just solve it again by reading the input axis and multiplying by the speed allowed like the system does under the hood. Ofc this isn’t the same as re-reading it and won’t always work (like if you use root motion or a curve to set the velocity for instance). It is however easy to work out in other ways if you dont want to access the character movement component… is it worth the effort? Maybe? Maybe not? In the end it’s what you like better so long as you don’t violate best practice standards…

I’m leaning more into a modular architecture like how you’d see in Lyra. In fact my project started out based on Lyra.

There’s quite a bit of work being done even in the ABP and some things don’t make sense to do in the character itself, so the rule there has to be 0 code can’t work. Unreal’s own examples and Lyra show doing things in threadsafe blueprint update with light amounts of code.

What you’re describing of putting things in the character and talking to the ABP creates extremely tight coupling. Any pawn could be the class. I also make use of Link Anim Layers and multiple layers of nested anim sub graphs that don’t all know about each other.

For example, my weapon animation anim subgraph knows nothing about the character or its parent anim bps. It got linked via link anim graph when I switched to that weapon. Inside the threadsafe update function, I’m trying to call something like

AbilitySystemComponentGetAlphaBlendValue(Equipment.Status.Equipping.Equipped)

and I have a custom ability system component class. And I can’t call that function from property access because it takes a single parameter. If I were to add a function like

AbilitySystemComponentGetAlphaBlendValueForEquipped()

This would work from property access no problem. But now I have to add these methods randomly in my code that makes the API less clean and more hardcoded.

This got me thinking about how property access nodes are doing the same work as doing things in the anim graph update method anyway. They’re just storing copies of data for use later in the anim worker thread of the anim BP. So is there actually anything wrong with having a little bit of light work done in the update method if all it’s doing is storing values when that’s exactly what property access nodes are doing?

I guess I could also profile it but I imagine this must be known information already.

My theory is maybe there’s a phase where all the property access nodes are running in parallel in native code and it’s read only thread access while if it’s explicitly done in blueprint it’s done sequentially across all anim bps.

Again, that’s the rule.
Either follow it or get head bashed later on.
Epic is notorious for doing NOTHING their developers tell them that a project NEEDS to do in their content samples.

Use the proper methods?
“What is Blueprint Interface for $100”

YES, again, it’s BAD PRACTICE.
It won’t magically become a “good thing” because you want it to. No more than 4+4 would become 24 because you wish it would…

In reality, the update event on an ABP is called pre and post character spawn so it misfires a lot. Half the engine methods (OnConstruction, OnBeginPlay, OnOverlap etc) are notorious for firing when they shouldn’t.

All that said, Lyra does things wrong. They never cared.
Should you do things wrong? I’d suggest you don’t, but you can literally (as always) do whatever you want.
Knowledge is power. I gave you some knowledge that you won’t really get from Epic since they do their ■■■■ best to make information about FasthPath disappear consistently…

With that in mind, if you truly don’t know that blueprint interfaces are the way to do things the right way when communicating between stuff (a character firing a gun, or equipping it), then you need to FIRST get the basic idea on how things are supposed to be built in OOP for Unreal, then go back to figuring out how to craft up your specific animation blueprint related stuff for your custom weapon system.

Additionally, let me fast track your system a couple weeks here.

Create a Weapon class template.
Add an Animation variable to it named “Equip”, set a default.
Add an animation variable called “fire”, so on..
Add a mesh variable,
Add speed, bullet weight, etc. variables.
Implement the basic interfaces needed.
Make the class function.
Create class instance.
Fill class instances with custom assets.
And that’s your basic weapon instancing system.

At that point usually, the character is told to look up what animation to use for the montage by poking into the weapon class, and sourcing the animation. All wrapped in it’s own little nice bow that doesn’t have you go nuts when you try and implement 20 different weapons…
And it’s done with montages. Not the ABP.
Because you care about your sanity. I hope.

That’s interesting, but where are the sources to the things you mentioned? I’ve never heard these things outside of this post. There are many tutorials out there that teach things counter to what you said.

I’m an experienced unreal dev myself, but never worked for a AAA company using unreal, so maybe it’s something more known deep in the AAA dev circles?

My weapon system is all working quite well and it’s all thought out already. You can assume I’m a seasoned principal software engineer in FAANG and know OOP and how to use interfaces really well. I use GAS and it plays anim montages and everything is solid.

I mostly had questions about best practices and how the property access nodes work.

I think you’re right, for simple stuff you’re not gaining much esp if it’s just for a few characters. The big benefits are when you’re doing lots of characters due to the parallelization and how it copies the data. Also, skipping the blueprint VM helps, too.

I think it’s fine to mix and match if needed. You’re pushing that other work off the game thread, regardless.

I would probably have lots of monsters running around to shoot at. In general if it’s possible to do it in the correct optimized way I’d do that.

Premature optimization is the root of all evil but in this case if I understand how the property access nodes work, then I can make correct assumptions about how things get optimized.

In this case I would definitely put the work in to optimize as much as possible seeing how heavy animation is. Depending on your NPC count you might consider mass entity plugin and using animtotexture to do your animations if you really want high numbers… although that’s a whole other level of optimization :slight_smile:

When it comes down to it, though, the only way to really know is to profile it on your target hardware. Insights will let you know pretty quickly if you’re eating too much time with your animations.