- Изменено
Interrupt looping animation after delay
Hello!
As far as I can tell, if you use SetAnimation() to play a looping animation, and then use AddAnimation() with a delay, it will wait the delay and then essentially cancel the loop, but the looping animation will complete its current iteration before playing the added animation.
From other forum posts I can see this is generally the desired behaviour, but I have a situation where I want the looping animation plus its outro to be an exact length (which is variable) so I need to interrupt that loop at an exact point, not waiting for the looping animation to complete its iteration.
Is there a setting that I can do that with? Currently I'm resorting to kicking off a coroutine and using SetAnimation() again after the desired delay, but I was hoping there was a way to do this within the spine structure.
Thanks!
seraphki написалFrom other forum posts I can see this is generally the desired behaviour, but I have a situation where I want the looping animation plus its outro to be an exact length (which is variable) so I need to interrupt that loop at an exact point, not waiting for the looping animation to complete its iteration.
I'm not sure I understand your question correctly. Do you mean that you have a single looping animation which consists of two parts, a loop-part
and outro-part
and want to exit this single animation after loop-part
? Have you considered using a negative delay
parameter at AddAnimation
as described here?
In general you can use TrackEntry animationTime to query at which playback time your animation currently is.
Yes, I have a looping animation with an outro. The problem is, I need the looping animation + the outro to be a very specific length, and that length is dynamic.
AddAnimation will always add the animation to the end of the queue, not fully interrupt at the end of the delay. So if my looping animation is 1s and my outro is 0.5s and I need the animation to be 5 seconds so I set the delay to 4.5s (total length minus outro length) at 4.5 seconds it doesn't interrupt, it just adds the outro to the end of the queue and stops looping, so the current looping animation will finish its iteration so the outro will start at 5s and I'll have a total length of 5.5s.
Using AddAnimation with a delay of <= 0 just uses the currently playing's remaining animation time as a delay, effectively still just adding it to the end of the queue. Which makes sense, since its called AddAnimation.
What I really want here is a delay argument in the SetAnimation method.
I have been able to accomplish this by having a coroutine wait the 4.5s (or whatever length, again, its very dynamic) and then use SetAnimation to cancel the loop, wherever it is, and start the outro. I was just hoping to avoid the coroutine.
If animation A is playing and you use AnimationState addAnimation
to play animation B after a delay with no mix duration, B starts after the delay and A ends at that same time.
If you play animation B with a mix duration, B starts after the delay and A continues playing as normal. Once the mix duration is reached, A ends and B continues on.
AnimationStateListener interrupt
is an event that occurs after the delay when B replaces A as the current entry. A doesn't stop playing though, "interrupt" is just the name of that event.
I don't understand "stops looping" and "cancel the loop". Nowhere in the above is looping affected.
If you want your animations to finish at a specific time, you need to queue them appropriately. Eg if A is 1s looping and B is 0.5s and you want to play A for 4s then B for 0.5s with a 0.25s mix duration:
state.setAnimation(0, "A", true);
entry = state.addAnimation(0, "B", false, 4);
entry.mixDuration = 0.25;
That says: A plays, after a 4s delay B begins mixing in over 0.25s. B will reach its animation duration 0.5s from when it started, which is 4.5s from when A started. From 4s to 4.25s A will continue to loop as B mixes in.
I have tried with the mix duration set to zero, and it just doesn't mix, as I expect. But I still don't interrupt the loop's current iteration. I might not be being clear enough about what I'm trying to accomplish. With this example setup:
Animation A: 1s duration
Animation B: 0.5s duration
I want the entire animation sequence, loops and outro, to be, for example, 5 seconds. So, I use this setup:
state.setAnimation(0, "A", true);
entry = state.addAnimation(0, "B", false, 4.5);
entry.mixDuration = 0;
From start to finish, this entire sequence will take 5.5 seconds to complete, and animation "B" will start playing at 5 seconds, not 4.5. After 4.5 seconds "B" is added to the end of the queue, and it waits for the currently executing loop of animation A (which after 4.5 seconds is 0.5s into its 1s loop) to finish before it plays animation "B". Where what I want is for animation A to end immediately and B to immediately start playing.
seraphki написалFrom start to finish, this entire sequence will take 5.5 seconds to complete
It will take 5s to complete.
seraphki написалanimation "B" will start playing at 5 seconds, not 4.5.
B will start playing at 4.5s.
seraphki написалAfter 4.5 seconds "B" is added to the end of the queue
B is added to the queue at the time you call addAnimation
.
seraphki написалand it waits for the currently executing loop of animation A (which after 4.5 seconds is 0.5s into its 1s loop) to finish before it plays animation "B".
It waits for the delay specified when you called addAnimation
, which is 4.5s.
There is no magic involved. When the delay is 4.5s then when A has been playing 4.5s, that is when B starts (the code). Nothing else is taken into consideration, not A's duration, loop completion, or anything else.
If you don't see the behavior as I have described, then something else must be going on. In that case we'd need to see the simplest possible code that shows the incorrect behavior.
Okie dokie. When I was trying to figure some of this out I was forum surfing and there were a couple forum posts where people seemed to be complaining about the opposite (AddAnimation interrupting the SetAnimation and not letting the loop finish) and I thought I'd seen someone say that it was either a bug or that they had an issue in their code, so I got the impression that it wasn't supposed to interrupt.
So, working off the assumption that non-interrupt was the desired behaviour, I just switched to a coroutine and just moving it to a coroutine and switching to set fixed my problem, further supporting that line of thought. But maybe did miss a weird value or a mis-timed clear. I'll dig some more and if I see that AddAnimation isn't interrupting I'll put together a simple script/project/whatever showcasing the issue.
Thank you!
Alright, did some tests and looks like it is something else!
Sorry for the red herring, I just really thought I'd seen in a couple other posts that non-interruption was the intended behaviour, and since it so matched up with what I was seeing I was running with that. Also, sorry if I was sounding abrupt. I thought I was being misunderstood, not that you didn't know what you were talking about
I found a piece of our animation controller that manipulates timescale, which in turn must have been manipulating the delay to not be quite right, triggering the outro late and making it look like it was waiting for that last loop.
Thanks for getting me back on track!
No worries, glad you got it figured out!