I’m attempting to move some Anim Blueprint logic over to a base C++ Anim Instance class, but can not figure out how to use the new Threadsafe Property Access System in C++.
There is no documentation on how to do this. My Anim Blueprint is making extensive use of the property access node, can anybody give a simple example of the equivalent in c++?
Hey, thank you. I actually just read this, but it’s not clear if this proxy is the same thing that is being done in the lyra example? I’m doing what they are doing and using the BlueprintThreadSafeUpdateAnimation function which accesses values using the propery access system node.
It’s has been easy moving most of the blueprint logic to my c++ anim instance class until I need to access a property that is using this node:
Are you saying the equivalent of this blueprint node in c++ is to use the anim proxy struct? Will it be safe to access proxy variables in my c++ anim instance thread safe functions?? If so do you know where I can find a better example then the docs linked? I have not been able to find anythign besides that doc, no forum posts, questions, blogs, etc…
Just to be clear, all I’m trying to do is “TryGetPawnOwner.GetActorLocation” in my c++ thread safe function. In blueprints it won’t let you make that function call unless you use the property access node, whereas in c++ im not sure how to do this.
If I was to follow that doc, its suggesting I create a proxy struct, update the GetActorLocation variable like I normal would (Just calling TryGetPawnOwner->GetActorLocation()) inside the proxy update, then back in the c++ anim instance function get the proxy to access the variable?
Should I move all my c++ anim instance variables over to the proxy? or just the variables that are using the property access system nodes (thread safe variables)?
Btw TryGetPawnOwner is not accessible from the Proxy. I’m guessing the correct way to get that would be to set an owner variable on the proxy during its initialization becuase it passes in the Anim Instance, and accessing the GetActorLocation() from that? Assuming everything else I said is correct.
Hi, sorry for so long answer. To be clear, I’m not an Animation Developer. But I’m also interested in this topic, maybe it would be easier for us to cooperate))
Just to be clear, all I’m trying to do is “TryGetPawnOwner.GetActorLocation” in my c++ thread-safe function. In blueprints it won’t let you make that function call unless you use the property access node, whereas in c++ im not sure how to do this.
If I understood correctly, this won’t be a thread-safe call, cause you’re trying to get info directly from Owner, outside of AnimInstance. That’s why EventGraph is empty in AnimBP. As they stating in doc about animation in Lyra:
“When using Thread Safe functions you can not access data directly from game objects as you could in the Event Graph. For example, if you were attempting to copy the Gameplay float value for the Character’s speed it would not be considered thread-safe, therefore we recommend the use of Property Access to accommodate these instances.”
I think you should use proxy stored variables only for property access.
I’m guessing the correct way to get that would be to set an owner variable on the proxy during its initialization becuase it passes in the Anim Instance, and accessing the GetActorLocation() from that?
I would do that. Maybe even tried to set all properties on init that I would need to have access to in future, like Location, Rotation, Velocity etc.
By the way, just run a simple test measuring exec time for different AnimBPs in the game thread.
ALS_AnimBP ≈ 180μs
Basic AnimBP (only owners rotation and velocity) ≈ 80μs
Lyra AnimBP ≈ 30μs
Measured by Unreal Insights. The test wasn’t perfect, just simple AIBot running and jumping through the level, but still interesting results. Maybe I should run a test with multiple bots to make a stress test.
Thank you for your input. Those are interesting test results, I was worried about performance as it seems like it would be worse using the proxy as it’s causing me to have some duplicate variables that already exists on my anim instance.
But as you said, the proxy is the only way to go. If you attempt to access properties outside the anim instance it will crash at runtime. Using the proxy I have not had any issues. Although its still not clear if I’m doing everything correctly, but I was able to get this working. (At least it appears to be).
The docs are actually incorrect, it wont compile if you copy what they do. Below is a simplified example of what I found to work. I also removed the proxy from being accessible in blueprints as it makes no sense because you can just use the property access node in blueprints.
Just for clarity for future readers, to access an updated property of the proxy, in your anim instance you simply ask the proxy:
Location = Proxy.ActorLocation;
Although there is still many questions about this proxy and the “correct” way to use it:
When to use PreUpdate, Update, or PostUpdate to update variables? I am currently doing everything with PreUpdate as it gives me access to the InAnimInstance.
Can I use the proxy to fill the variables directly on my anim instance instead of having a copy variable on the proxy that is being filled?
Can I access something on the Anim Instance directly in a thread safe function without the proxy? Like bIsAnyMontagePlaying.
Is it safe to use InitializeObjects to cast to the correct anim instance, pawn owner, and movement component, and stores those values on the proxy without issues, or should we just grab, cast, and check for null each time from the InAnimInstance on PreUpdate?
Thank you for the research that you’ve done! Great job!
Sorry, I can’t help you with those questions, they are outside of my level of expertise, but I wish I could(
Saved your post, it will definitely help me in the future!
Instead of doing any of this proxy stuff, cant we just use NativeThreadSafeUpdateAnimation override?
If you look at lyra, all the calculations are done in BlueprintThreadSafeUpdateAnimation . So following the same pattern cant we just make normal BP read-only Uproperties in UAnimInstance in c++. Do calculations and set those value in NativeThreadSafeUpdateAnimation override function?
If you peak NativeThreadSafeUpdateAnimation definition , the comment says “// Native thread safe update override point. Executed on a worker thread just prior to graph update
// for linked anim instances, only called when the hosting node(s) are relevant”
So from what I understand, this function 1) runs on a worker thread 2) Runs before anim graph thus making all our calculations available to use.
As far as accessing external values such as character world position or acceleration or velocity etc goes, those are being read not modified. So there shouldn’t be any problem there.
So like do you even need a property access system equivalent in c++? One problem that I can think of is if worker thread ran more than once before the main thread then that would result in
a property having same value over multiple ticks.
One hack that I can think of is I guess use a bool initialize it to false. Make it true every tick in NativeUpdateAnimation. Then in NativeThreadSafeUpdateAnimation check if the bool is true.
If true then do calculations and set it to false, if bool is false then skip this tick. This way we know that main thread has had a chance to run before worker thread.
I cannot overstate the importance of reading and understanding this document. I’m fairly experienced in this area, but I was completely not involved in Unreal when the switch to multi-threaded animations occurred, so I completely missed this information.
This should be required reading for anyone working with ABPs.
Can confirm this seems to be working fine for me. I tested by created a native c++ anim instance and doing all logic in the NativeThreadSafeUpdateAnimation. I noticed no issues without using a proxy.
Would be interesting to see the performance difference between native thread safe, proxy, and blueprint property access.
I too would be interested in the performance test.
I’m currently working with State node functions in C++, threadsafe stuff etc etc, I have not explored the proxy option and no issues so far.
Created procedural turn in place, start/stop/pivot, orientation warping, speed warping, bank warping and all that so a lot of functions and variables, if there was an absolute need for a proxy I feel like I should have run into it by now
For the native State node functions did you decorate the UFUNCTION with “meta = (BlueprintThreadSafe)” ? Did it work for you? I get the error that the functions are not thread safe
Yes, you need to make the UFUNCTION both BlueprintCallable and meta = (BlueprintThreadSafe). You cannot be doing anything inside the function that is not thread safe or you will get that error. You also must call the function only from anywhere it is thread safe. i.e. NativeThreadSafeUpdateAnimation, BlueprintThreadSafeUpdateAnimation, OnUpdate, OnBecomeRelevant State Nodes…
This is basically just like using a regular AnimInstance, but you’re consolidating all of your variables and update activity in the FAnimInstanceProxy, which is a friend struct of the AnimInstance. I’m not actually sure why the Proxy would need to access the AnimInstance’s variables (I’m sure someone out there knows something I don’t).
The Proxy is where you would put your variables, and you can think of virtual void update() override almost like NativeUpdateAnimation. There are additional functions like FAnimInstanceProxy::PreUpdate, FAnimInstanceProxy::PreEvaluateAnimation, and FAnimInstanceProxy::PostUpdate that you can implement and use in addition to update() depending on your use cases (I haven’t used these, myself).
In your Animation Blueprint, you can use the property access from the right-click context menu and access your variables via Proxy.<variable>.
From what I gather, the Proxy is basically a wrapper for your AnimInstance data that’s automagically managed by UE’s multi-threaded animation update system. I believe there’s no need to worry about locks or synchronization. Using “Property Access” to read your variables into your animation blueprint ensures that they will only be accessed when it is safe for the blueprint to do so (less for you to worry about).
To be honest, I haven’t really used it that much and I would just stick with the blueprint stuff and avoid the FAnimInstanceProxy