briang

I'm looking to programmatically advance an animation frame-by-frame from the first frame to last frame. I also want to listen for Spine events along the way (Start, End, Complete, and custom events).

Thanks to Mitch’s code example (from http://esotericsoftware.com/forum/Unity-Need-to-set-a-animation-to-a-specific-frame-4714), I am able to use SkeletonRender to programmatically move frame by frame.

But now I’m wondering if there is also a way to trigger start, end, complete events available in SkeletonAnimation? Being a newbie, I’m not sure if I can mix these two approaches (SkeletonRenderer and SkeletonAnimation), or if I'm on my own to figure out events using the SkeletonRenderer approach. All suggestions much appreciated.

Here's my adapted code from Mitch's example:
using UnityEngine;
using System.Collections;
using Spine;

[ExecuteInEditMode]
[RequireComponent(typeof(SkeletonRenderer))]
public class FrameByFrame : MonoBehaviour{

[Range(0,232)] // between 0 and 232 frames
public float frame = 0;

[SpineAnimation]
public string animationName;
Spine.Animation animation;

SkeletonRenderer skeletonRenderer;
Skeleton skeleton;

void Start () {
skeletonRenderer = GetComponent<SkeletonRenderer>();

skeleton = skeletonRenderer.skeleton;

// can I create an animation state and listen to its progress
// while manually controlling the animation from skeletonRenderer.skeleton?
// following does not work, not sure of the correct approach
Spine.AnimationStateData stateData = new Spine.AnimationStateData(skeleton.data);
Spine.AnimationState state = new Spine.AnimationState(stateData);
state.SetAnimation(0, animationName, false);
state.End += MyEndListener;
}

public void MyEndListener(Spine.AnimationState state, int trackIndex){
Debug.Log(trackIndex + " " + state.GetCurrent(trackIndex) + ": end ");
}

void Update () {

if (skeleton == null)
return;

if (animation == null) {
animation = skeleton.Data.FindAnimation(animationName);
if (animation == null)
return;
}

int frameCount = (int) ((animation.duration * 30f));
float jumpto = ((float)frame/frameCount) * animation.duration;

animation.Apply(skeleton, 0, jumpto, false, null);
skeleton.Update(Time.deltaTime);
skeleton.UpdateWorldTransform();
}
}
briang
  • Сообщения: 1

Pharan

AnimationState keeps track of times and animations, and then calls animation.Apply based on the time it keeps, and fires events based on that and the duration the animation it's playing.
Start, End and Complete are tied to AnimationState logic depending on what time it detects and it's tied to its internal track system.

If you are advancing the animation yourself and keeping track of time yourself, you should fire your own events.
Your code's logic doesn't even use AnimationState (never updates it, doesn't need to apply it because you are applying animations directly) so there's no need for it to be there.
Аватара пользователя
Pharan
  • Сообщения: 5366


Вернуться в Unity