Closed slowhei closed 3 months ago
Pausing Animancer instead of stopping it should do what you want:
animancer.Playable.PauseGraph();
But if you're only ever playing one AnimationClip
on that object, it would be more efficient to use a Solo Animation component instead of an AnimancerComponent
. Then you can achieve the same thing by setting its IsPlaying
property to false
.
Thank you! PauseGraph
did the trick.
Hello,
I have come to realize that modifications to transform.position
on the same frame PauseGraph
is called results in those modifications being reverted by the next frame.
Here is the specific scenario I am observing:
animancer.Playable.PauseGraph();
Debug.Log(transform.position); // output: (1, 1, 1)
transform.position = new Vector3(0, 0, 0);
Debug.Log(transform.position); // output: (0, 0, 0)
// but on the next frame...
Debug.Log(transform.position); // output: (1, 1, 1)
Is there any way to prevent transform.position
from being reset?
Can you post your full code? I did a quick test and wasn't able to replicate the issue you're describing.
Of course. Here is a link to a zip file containing a small Unity project that reproduces the issue: // Link Removed
Once you unzip and open the Unity project, all you have to do is press play and observe the console output.
I should also explain what is going on in this project.
LAB_TransformResetBug_Character
attached to it. "Projectile" has `LAB_TransformResetBug_Projectile" attached to it.LAB_TransformResetBug_Character.Start
is the entry-point of all of the code I wrote.Let me know if anything goes wrong or if you have any other questions. Thanks.
I've downloaded it and will take a look tonight, but please take down that file and don't share projects containing Animancer in the future.
I am so sorry!!! I updated the sharing permissions. Now no one can access it.
Another tip for if you need to send someone a project: you only need Assets, Packages, ProjectSettings, and UserSettings. Everything else can be regenerated by Unity, particularly the Library folder which was 1.3 GB in your project and the actual necessary stuff is only 36 MB.
The cause of the problem (and the reason my test didn't catch it) is the fact that you're doing it in an Animancer Event. Pausing the graph will stop it from being updated, but events are triggered while its already in the middle of being updated and the pause won't stop it from applying its output.
To avoid the issue you'll need to delay until LateUpdate
or use yield return new WaitForEndOfFrame();
if you're in a coroutine (store it in a static field to avoid allocating unnecessary garbage every time).
This won't be a problem any more in Animancer v8.0 because I've moved events to be invoked in LateUpdate
anyway.
Thanks for the tip about sending a project. I was wondering why my zip file was still 700+ MB even though I didn't put much in there...
I see, so my changes to the transform are being overwritten by Animancer after the Animancer events fire. And yup, LateUpdate
and yield return new WaitForEndOfFrame()
both work.
But I have other scripts running during Update
that rely on the transform being set to the correct value on the exact frame the Animancer event is invoked. I can't wait until LateUpdate
to update the transform. So instead, I think I will use IUpdatable
and AnimancerPlayable.RequirePostUpdate
toupdate the transform.
If in version 8, Animancer events are invoked in LateUpdate
, do you expect what I'm doing (forcing code to run after the Animancer update, but before all other scripts run Update
, and defining the timing using an Animancer event) to still be possible?
Thank you!
Events are run by an IUpdatable
in the post update so doing your stuff there might not reliably run after them because there's no execution order control within the post update list and that's still inside the animation update before it has applied the animation output to the model that frame.
I'm not sure why you think LateUpdate
would be a problem for whatever you're doing in Update
. A frame consists of Update -> AnimationUpdate -> LateUpdate -> Render
so anything you do in Update
won't be able to tell the difference between something that was done in the last AnimationUpdate
or LateUpdate
.
The new system using LateUpdate
has a [DefaultExecutionOrder]
attribute set to -30000 (the minimum is -32000) which should make sure its the first thing to run after the animation update so it should be generally indistinguishable from the old behaviour except that it happens after the animation output has already been applied.
Gotcha. You're right. I got the Unity order of exeuction wrong. I thought animation updates came before Update
.
Hello,
I have a GameObject whose transform is controlled by Animancer using a
ClipTransition
. There is no bone hierarchy or anything fancy. It's just one GameObject with anAnimancerComponent
and no child GameObjects.Once the animation ends, I want to completely disable Animancer so that the transform can be controlled using a
Rigidbody
also attached to that GameObject. BUT, stopping Animancer resets the transform to its prior position, and I don't want that.I have tried saving the transform's position before disabling Animancer and then reapplying it afterwards, but the transform position still gets reset. (Below is what I am doing:)
How can I stop Animancer without resetting the transform?
Thanks.