KybernetikGames / animancer

Documentation for the Animancer Unity Plugin.
63 stars 8 forks source link

How to stop duplicate states piling up in animancer #334

Closed thatgreatAlice closed 4 months ago

thatgreatAlice commented 4 months ago

Captura de pantalla (685)

I would like to know how to stop all the states piling up like this in animancer. When the same animation has to be played on repeat it can create many duplicate states as seen in the image attached. I understand that it needs two states at any time for the cross fade to work but having so many states causes issues where all the states with the same animations play at the same time and the animation just bugs out.

For context, I just take the AnimancerClip and use the Animancer.Play() method but it seems like that isn´t the right approach.

KybernetikGames commented 4 months ago

If it's creating more than two, then you're telling it to play more than twice in a row before the previous fades are complete. Your screenshot shows that they're all at different times which wouldn't be possible with only two states.

You can modify the static AnimancerLayer.WeightlessThreshold and AnimancerLayer.MaxCloneCount to control when clones are created and how many it can make.

Otherwise, maybe FadeMode.FromStart isn't right for this situation. You say the current setup is causing the animation to bug out, but what are you expecting it to look like when you repeatedly restart the same animation?

thatgreatAlice commented 4 months ago

The screenshot I showed is just one of the possible unexpected errors that can happen. Sometimes, when it´s in the middle of an animation and I want to interrupt that animation with the same animation (In the game you are staggering the opponent multiple times hence the repeat in animation), the animation doesn´t play at all, and other times, when I am clearly only playing the animation once, it creates 3 duplicate states. Sorry if what I explained isn´t super congruent, I don´t really know what the true cause of the issue is.

What I don´t get is why the animancer component even creates more than 2 animation states at any given time. In reality the only states it should have is the one it was previously playing and the one it is fading into, no? I just want to be able to play cliptransitions on demand in code, but I feel as though there is a lot going under the hood that I am not understanding.

KybernetikGames commented 4 months ago

If you tell it to play an animation and it doesn't, that's a bug. Please send a minimal reproduction project to animancer@kybernetik.com.au so I can look into it.

Same if it creates multiple states in one call. That shouldn't be possible.

It creates another state if none of the existing states are below the AnimancerLayer.WeightlessThreshold. So if the character is already in the middle of fading between a state and its clone with neither state below that threshold, it will need to make another in order to smoothly transition into it.

thatgreatAlice commented 4 months ago

Ok so after some testing the duplicate states were my fault and you were right they were being called extra times when they shouldn´t. That being said the issue where sometimes I try to play the same animation to interrupt the one currently being played still occurs. I will send you the project for you to test it.

Also, for some reason I also have the bug where animancer ignores the modifications I made to the cliptransition (changed endtime) and plays the default animation. No idea why, so if you could give me some guidance on why that happens, I would be very grateful.

KybernetikGames commented 4 months ago

The only issue I can see in the project you sent me is that the transition didn't have its Start Time enabled so it would only play the animation once and subsequent plays let it continue from wherever its at instead of restarting it or making clones. Ticking the Start Time makes it restart the animation and create clones as expected.

The End Time doesn't actually have any direct effect by default, it just defines when the End Event will be called. But since the project you sent me isn't registering a callback to it, its not doing anything and just lets the animation finish playing.

thatgreatAlice commented 4 months ago

Ah I see, sorry for taking up your time then. But what if I want to play an animation and have it end at the endTime? That´s what I was going for but couldn´t achieve

On Mon, Apr 1, 2024 at 1:48 AM Kailas Dierk @.***> wrote:

The only issue I can see in the project you sent me is that the transition didn't have its Start Time enabled so it would only play the animation once and subsequent plays let it continue from wherever its at instead of restarting it or making clones. Ticking the Start Time makes it restart the animation and create clones as expected.

The End Time doesn't actually have any direct effect by default, it just defines when the End Event will be called. But since the project you sent me isn't registering a callback to it, its not doing anything and just lets the animation finish playing.

— Reply to this email directly, view it on GitHub https://github.com/KybernetikGames/animancer/issues/334#issuecomment-2028952502, or unsubscribe https://github.com/notifications/unsubscribe-auth/AP7AFNPRZPV6TJHHBNDDN4TY3COGHAVCNFSM6AAAAABFOZEGYGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDAMRYHE2TENJQGI . You are receiving this because you authored the thread.Message ID: @.***>

KybernetikGames commented 4 months ago

It depends on what you actually mean by "end", that's why it's a callback where you can do whatever you want.

In most cases you want to just play something else which will automatically stop the previous animation.

Or if you want the character to freeze in place, you could use the callback to call:

animancer.Playable.PauseGraph();

In that case you'd also need to call UnPauseGraph next time you want it to play something.

thatgreatAlice commented 4 months ago

Yeah I basically want to truncate the animation and have it freeze on the last frame, sorry for not making that clear, but yes I shall try using PauseGraph, though having to unpause it everytime seems like a bit of a hassle. Thanks either way!

On Mon, Apr 1, 2024 at 1:44 PM Kailas Dierk @.***> wrote:

It depends on what you actually mean by "end", that's why it's a callback where you can do whatever you want.

In most cases you want to just play something else which will automatically stop the previous animation.

Or if you want the character to freeze in place, you could use the callback to call:

animancer.Playable.PauseGraph();

In that case you'd also need to call UnPauseGraph next time you want it to play something.

— Reply to this email directly, view it on GitHub https://github.com/KybernetikGames/animancer/issues/334#issuecomment-2029633045, or unsubscribe https://github.com/notifications/unsubscribe-auth/AP7AFNKDGL3X6IYSMAQCQRDY3FCBLAVCNFSM6AAAAABFOZEGYGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDAMRZGYZTGMBUGU . You are receiving this because you authored the thread.Message ID: @.***>

KybernetikGames commented 4 months ago

If you don't mind the performance being a tiny bit worse, the Event Utilities example explains how you can pause only that state so you don't need to worry about unpausing when you play something.

thatgreatAlice commented 4 months ago

Oh awesome and thanks for these quick replies. I was wondering if I were to interrupt that animation with another of the same animation, would "CurrentState.IsPlaying" still remain false, or would it reset to true after using the Play() method?

On Mon, Apr 1, 2024 at 3:36 PM Kailas Dierk @.***> wrote:

If you don't mind the performance being a tiny bit worse, the Event Utilities https://kybernetik.com.au/animancer/docs/examples/events/utilities#pause-at-current-event example explains how you can pause only that state so you don't need to worry about unpausing when you play something.

— Reply to this email directly, view it on GitHub https://github.com/KybernetikGames/animancer/issues/334#issuecomment-2029770217, or unsubscribe https://github.com/notifications/unsubscribe-auth/AP7AFNL2UWVEKJ3EUN3V75DY3FPEFAVCNFSM6AAAAABFOZEGYGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDAMRZG43TAMRRG4 . You are receiving this because you authored the thread.Message ID: @.***>

KybernetikGames commented 4 months ago

IsPlaying indicates whether the state is playing so calling Play would obviously set it to true.