- 編集済み
How to really stop the animation?
I have two methods. One opens the window and starts the animation, the other turns off the animation and closes the window.
The first time the animation plays as it should. A logo emerges from the void. But when I open window again, I see the logo, it disappears and only then starts to appear. SetEmptyAnimation doesn't stop the animation, it moves it to the last frame. How can I turn off the animation so that I see an empty frame?
void OpenWindow()
{
parentMySpineAnimation.SetActive(true);
mySpineAnimation.AnimationState.SetAnimation(0, "start", false);
}
void CloseWindow()
{
parentMySpineAnimation.SetActive(false);
mySpineAnimation.AnimationState.SetEmptyAnimation(0, 0);
}
p.s. Please tell me why you didn't just add static StopAllAnimation? It's not so convenient.
mySpineAnimation.AnimationState.ClearTracks()
should do the trick in CloseWindow()
.
It just stops the animation. I would like to clear the image completely. Well, or at least put the very first frame of the animation I need, without playing.
I'm not sure I understand you correctly. If you mean that you want all animations to stop playing and to return the skeleton's state to the setup pose, then you can call skeletonAnimation.Skeleton.SetToSetupPose()
after skeletonAnimation.AnimationState.ClearTracks()
.
WindArt wroteBut when I open window again, I see the logo, it disappears and only then starts to appear.
If you were using the default MixDuration when applying the animation, then it will blend from whatever its current state is, into the animation. So if its current state is that the logo is being shown, and the beginning of the animation is the logo invisible, then it will quickly blend from being visible to invisible. You can try setting the MixDuration to 0.
Side note - if there is no animation on the Track Index that you are applying these animations to, then when you set the animation it will instantly pop into the first frame of the animation. But if there is already an animation on the track (if you played the animation, and it completed and you didn't clear the track, then it will sit on the final frame of that animation) then it will use the default MixDuration if you don't specify it, which is 0.1 or 0.2 seconds (can't remember).
WindArt wroteSetEmptyAnimation doesn't stop the animation, it moves it to the last frame.
SetEmptyAnimation would essentially clear the track - it wouldn't sit on the last frame of the animation. Does the last frame of the animation match your Setup pose (both showing the full logo)? You might be mixing up the two.
Another option to consider (since I'm not fully sure of what you're doing) - If your Setup pose shows your whole logo (meaning that clearing the track reverts your skeletonAnimation to showing the logo), but you want to 'clear the image', then you can make an animation that is just a single frame of your logo in the invisible/cleared state, and apply that.
I found a solution in another section of the forum. http://ru.esotericsoftware.com/forum/How-to-set-first-frame-before-animation-starting-in-Unity-13161
I have to add updating the animation manually when the window is opened.
void OpenWindow()
{
parentMySpineAnimation.SetActive(true);
mySpineAnimation.AnimationState.SetAnimation(0, "start", false);
mySpineAnimation.Update(0); // add this
mySpineAnimation.LateUpdate(); // add this
}
Why isn't this added automatically by one method? For example
mySpineAnimation.AnimationState.PlayAnimIgnorAll(0, "start", false);
instead
mySpineAnimation.AnimationState.SetAnimation(0, "start", false);
mySpineAnimation.Update(0);
mySpineAnimation.LateUpdate();
Glad you've figured it out.
WindArt wroteI have to add updating the animation manually when the window is opened.
[..]
Why isn't this added automatically by one method? For example
Calling skeletonAnimation.Update(0);
is only necessary when setting the animation "too late" in the script execution order. SkeletonAnimation.Update()
applies the animation state to the skeleton, SkeletonRenderer.LateUpdate()
then generates the Mesh based on the current skeleton state. So when changing the animation after it has been applied, you will see it in the next frame.
I understand that this situation is not ideal, sorry for the trouble. The design-wise reason that there is no automatic tracking of whether Update()
needs to be called is that the used AnimationState class does not know anything about the enclosing SkeletonAnimation
component class. What would be needed is to provide wrapper methods for all AnimationState methods in SkeletonAnimation
, duplicating the existing AnimationState API. We are currently in major restructuring of the main skeleton components of the spine-unity 4.1-beta runtime, I will consider whether adding a wrapper SkeletonAnimation.AnimationState
facade object could be done, which should serve the purpose of automatically tracking required updates and still keep the API backwards-compatible.
Thank you for the clarification.
Sorry for the possibly overly emotional statement. I just want the code to be easy to write.
Thank you again.
No need to apologize, your input is always welcome and absolutely justified. We hope to be able to improve the situation in 4.1-beta (without adding too much overhead).