- Edited
Get animation played on specific track?
skeletonAnimation.AnimationName gives me the name of the current animation, but when I'm using multiple tracks, how do I get the animation name of a specific track?
This works, but I don't feel it's the optimal solution
if (targetAttackAnim != null && !skeletonAnimation.state.ToString().Contains(targetAttackAnim.Name)) {
Don't use AnimationState.ToString()
, use AnimationState getCurrent to query the TrackEntry at a given trackIndex
.
In general you should reconsider your approach, as it is not considered good design to store player state in the low-level animation component and query it from there every time. Instead it would be recommended to store the state in your higher-level Player component. If you want to react to the end of e.g. an attack animation, you could register to AnimationState events:
spine-unity Runtime Documentation: Processing AnimationState Events
Thanks! Randomly I found getCurrent in another forum thread, but I will try it.
What i'm doing here is to check if the specific animation is already set, and if not, set it.
I'm using a custom state on the monobehavior like IDLE/WALK, then the method i mentioned above is checking what the state is, and switching animation if it's not already set.
Is this something that could be wasteful to resources? This code is run on each frame, and the ActionState is set from different places.
Thanks in advance for your advice!
case ActionState.IDLE:
// When in attack mode, show idle attack animation
if (
(subState == SubState.ATTACK || subState == SubState.ATTACK_WAIT)
&& skeletonAnimation.AnimationName != AttackWaitAnim.Name) {
// Attack idle
SetAnim(0, AttackWaitAnim, mix: defaultMixDuration, loop: true);
} else if (subState == SubState.IDLE && skeletonAnimation.AnimationName != IdleAnim.Name) {
// Normal idle
SetAnim(0, IdleAnim, mix: defaultMixDuration, loop: true);
}
break;
case ActionState.WALK:
if (WalkAnim != null && skeletonAnimation.AnimationName != WalkAnim.Name) {
SetAnim(0, WalkAnim, mix: defaultMixDuration, loop: true, alpha: 1, timeScale: walkAnimSpeed);
}
break;
}
nicmar wroteIs this something that could be wasteful to resources? This code is run on each frame, and the ActionState is set from different places.
While it's not optimal in terms of unnecessary computation (many string comparisons are rather costly, reference comparisons are of course better here), it most likely won't be noticable with only a few characters. It's just that code maintenance will become harder and the number of branches or if-conditions might multiply when explicitly querying every possible animation.
It might be easier to maintain code if you separate code that changes from one to another state
from the code that is performed when already in a state
.
So you would then replace the animation query code with:
if ((oldState != currentState) || (oldSubState != subState)) {
TransitionToState(currentState, subState);
}
UpdateInState(currentState, subState);
oldState = currentState;
oldSubState = subState;
...
void TransitionToState(ActionState state, SubState subState) {
if (subState == SubState.ATTACK || subState == SubState.ATTACK_WAIT) {
SetAnim(0, AttackWaitAnim, mix: defaultMixDuration, loop: true); // Attack idle
// perform other things that are necessary only once when changing
}
if (subState == SubState.IDLE) {
SetAnim(0, IdleAnim, mix: defaultMixDuration, loop: true); // Normal idle
// perform other things that are necessary only once when changing
}
}
void UpdateInState(ActionState state, SubState subState) {
if (state == ActionState.HEALING)
// add health points over time, etc.
}