官方文档:http://zh.esotericsoftware.com/spine-unity
但是我们又不得不用不是,所以就要自己翻它代码,找真正能调用的api了,这里推荐还是看一看它的官方文档,可以至少让我们对它的架构思路有一定的理解,方便快速分析它的真.api
都是用来干什么的~
以下以一个单通道的动画控制脚本来说一下。(这里要提个醒,spine它里面有个多通道的功能,可以让动画只作用于网格的某一部分上,比如我们有一个跑步的动画,依靠通道,我们可以实现在跑步的同时,让人能够挥手,或者扭头,用高级别的通道去覆盖低级别上的动画)
using UnityEngine;
using Spine.Unity;
using Spine;
/// <summary>
/// 单通道spine助手
/// </summary>
public class SingleTrackSpineHelper
{
public GameObject gameObject;
public Transform transform;
/// <summary>
/// 当前通道
/// </summary>
public int currentTrack = 0;
// 骨骼动画对象
private SkeletonAnimation _skeletonAnimation;
// 通道实体
private TrackEntry _trackEntry;
/// <summary>
/// 构造
/// </summary>
public SingleTrackSpineHelper(GameObject gameObject)
{
this.gameObject = gameObject;
this.transform = this.gameObject.transform;
_skeletonAnimation = this.gameObject.GetComponent<SkeletonAnimation>();
}
/// <summary>
/// 停止
/// </summary>
public void Stop()
{
_skeletonAnimation.state.ClearTrack(currentTrack);
}
/// <summary>
/// 根据时间播放
/// </summary>
/// <param name="animationName">动画名</param>
/// <param name="loop">true=循环,false=单次</param>
/// <param name="fromTime">开始时间(单位秒)</param>
/// <param name="toTime">结束时间(单位秒)</param>
public TrackEntry PlayByTime(string animationName, bool loop = false, float fromTime = -1, float toTime = -1)
{
this.Stop();
_trackEntry = _skeletonAnimation.state.SetAnimation(currentTrack, animationName, loop);
if (fromTime >= 0)
{
_trackEntry.TrackTime = fromTime;
}
if (toTime >= 0)
{
_trackEntry.TrackEnd = toTime;
}
return _trackEntry;
}
/// <summary>
/// 根据帧数播放
/// </summary>
/// <param name="animationName">动画名</param>
/// <param name="loop">true=循环,false=单次</param>
/// <param name="fromFrame">开始帧</param>
/// <param name="toFrame">结束帧</param>
public TrackEntry PlayByFrame(string animationName, bool loop = false, int fromFrame = -1, int toFrame = -1)
{
float fromTime = -1;
if (fromFrame >= 0)
{
fromTime = (float)fromFrame / SpineConst.FRAME_UNIT;
}
float toTime = -1;
if (toFrame >= 0)
{
toTime = (float)toFrame / SpineConst.FRAME_UNIT;
}
return this.PlayByTime(animationName, loop, fromTime, toTime);
}
/// <summary>
///
/// </summary>
/// <param name="animationName"></param>
/// <param name="loop"></param>
/// <returns></returns>
public TrackEntry Play(string animationName, bool loop = false)
{
return this.PlayByTime(animationName, loop, -1, -1);
}
}
如果我们只是播简单的动画的话,封装的这个小控制脚本就足够了。 _skeletonAnimation.state
这个是我们获取当前动画和播放动画的主要方法,文档有说,就不累赘了。
当我们有需求中间打断一个动画,让它重头开始时,我们第一时间想到的肯定是这样来: _skeletonAnimation.state.SetAnimation(currentTrack, animationName, loop);
然鹅,并没有卵用,单纯的这样调一下,你会发现动画会从当前的地方往回拉,动画完全不会重头进行播放,这根本不是我们想要的结果。
正确的做法应该是先用 _skeletonAnimation.state.ClearTrack(currentTrack);
来停止当前正在运行的通道,然后再重新播放这个动画,这时你就发现动画是真的重头开始了,而不是往回拉了。。。
而当我们只需要播放时间轴上某一段动画的时候,也根本不是官方所说的方法,而是需要用 _trackEntry.TrackTime
和_trackEntry.TrackEnd
这2个方法,它们控制了当前通道下播放动画的起止时间!