cocosCreator笔记 之Spine

版本: 3.4.0

参考:

Spine 骨骼动画资源

Spine Skeleton组件

cocosLua 之 骨骼动画


简介


使用spine动画,cocosCreator目前支持的版本:

creator版本spine版本
V3.0 及以上v3.8(原生平台不支持特定版本 v3.8.75)
v2.3 及以上v3.8
v2.2v3.7
v2.0.8~v2.1v3.6
v2.0.7 及以下v2.5

spine骨骼动画所需资源主要有如下三种:

  • .png 动画图片相关
  • .txt/.atlas 图集配置数据相关
  • .json/.skel 骨骼数据配置相关

spine骨骼动画主要组成部分:

  • bones 骨骼相关,基本组成元素,存在父子关系;每个骨骼可关联多个slot相关
  • slots 插槽相关, 主要用于关联多个attachment相关
  • attachment 附件相关, 有Mesh, BoundingBox, SkinnedMesh等不同类型
  • skins皮肤相关
  • animations 动画相关
  • ik

在cocosCreator中使用spine动画,官方封装的组件是sp.Skeleton


sp.Skeleton组件的使用


通过编译器添加spine动画,大概步骤:

  • 层级管理器创建一个空节点,假设命名为spine_node
  • spine_node属性检查器中,添加组件,搜索skeleton添加进来
  • 可把UITransform的锚点修改为(0.5, 0)

请添加图片描述

如果在脚本中使用property声明类型的时候注意:

  • 如果为sp.Skeleton类型,在脚本中可以直接对骨骼动画进行处理
  • 如果声明为Node类型,在脚本中需通过getComponent(sp.Skeleton)获取组件,再进行处理
export class DebugLayer extends Component {
  @property(Node) 
  spineNode: Node = null;
  
  private _spine: sp.Skeleton = null;
  onLoad() {
    this._spine = this.spineNode.getComponet(sp.Skeleton);
  }
  
  onEnable() {
    // 使用Node类型,可以添加对spine动画的触摸事件
    this.spineNode.on(Node.EventType.TOUCH_END, this._touchSpineEvent, this);
  }
  
  private _touchSpineEvent() {
    console.log("you touch spine");
  }
}

cocosCreator通过Skeleton对spine骨骼动画封装了很多方法:

export class Skeleton extends Renderable2D {
  // 是否循环播放
  loop: boolean;
  // 当前骨骼动画是否暂停
  get paused(): boolean;	
  // 当前播放的动画名称
  get animation(): string;	
  // 设置动画播放速度,数值越大,播放速度越快
  get timeScale(): number;
  // 是否显示slot的测试信息
  get debugSlots(): boolean;
  // 是否显示bone的测试信息
  get debugBones(): boolean;
  // 是否显示mesh的测试信息
  get debugMesh(): boolean;
  // 是否启用染色效果
  get useTint(): boolean;  
  // 设置皮肤,比如切换衣服
  setSkin(skinName: string): void;
  // 设置附件,比如切换武器
  setAttachment(slotName: string, attachmentName: string): void;
  // 设置两个动画之间的混合时间,可以优化两个动画之间切换不连贯
  setMix(fromAnimation: string, toAnimation: string, duration: number): void;
  // 设置当前动画。队列中的任何的动画将被清除
  // 可以理解:如果前面有动画正在播放,且不管是否循环,会直接停止,然后播放设置的动画
  setAnimation(trackIndex:number, name:string, loop:boolean):spine.TrackEntry;
  // 添加一个动画到动画队列尾部,还可以延迟指定的秒数
  // 可以理解:该动画会等待当前播放的动画在单次循环结束后,开始播放
  addAnimation(trackIndex, name, loop, delay:number): spine.TrackEntry;
 
  // 还原到起始动作, 它主要用于处理上个动作留下的残影效果
  setToSetupPose(): void;
  setBonesToSetupPose(): void;
  setSlotsToSetupPose(): void;
  
  // 根据骨骼名字获取骨骼信息
  findBone(boneName: string): spine.Bone | null;
  // 根据关节名字获取关节信息
  findSlot(slotName: string): spine.Slot | null;
  
  //
  get sockets(): SpineSocket[];
  get socketNodes(): Map<number, Node>;
  /*
  * 若想切换渲染模式,最好在设置'dragonAsset'之前,先设置好渲染模式,否则有运行时开销。
  * 若在编辑中设置渲染模式,则无需担心设置次序的问题。
  */ 
  setAnimationCacheMode(cacheMode: AnimationCacheMode): void;
  // 当前是否处于缓存模式
  isAnimationCached(): boolean;
  // 通过 track 索引获取 TrackEntry
  getCurrent(trackIndex: number): spine.TrackEntry | null;
  // 清除所有 track 的动画状态
  clearTracks(): void;
  
  /*
  spine事件回调相关,它们主要用于对应:
  Start: 用来设置开始播放动画的事件监听
  Interrupt: 用来设置动画被打断的事件监听
  End: 用来设置动画播放完后的事件监听
  Dispose: 用来设置动画将被销毁的事件监听
  Complete: 用来设置动画播放一次循环结束后的事件监听
  Event: 用来设置动画播放过程中帧事件的监听
  */
  setStartListener(listener: TrackListener): void;
  setInterruptListener(listener: TrackListener): void;
  setEndListener(listener: TrackListener): void;
  setDisposeListener(listener: TrackListener): void;
  setCompleteListener(listener: TrackListener): void;
  setEventListener(listener: TrackListener2): void;
  // 增加了trackIndex相关
  setTrackStartListener(entry: spine.TrackEntry, listener: TrackListener): void;
  setTrackInterruptListener(entry, listener: TrackListener): void;
  setTrackEndListener(entry, listener: TrackListener): void;
  setTrackDisposeListener(entry, listener: TrackListener): void;
  setTrackCompleteListener(entry, listener: TrackListener2): void;
  setTrackEventListener(entry, listener: TrackListener | TrackListener2): void;
}

关于trackIndex一般情况下默认为0,如果要获取当前动画的索引,可以这样:

// 设置开始播放动画的事件监听
this.monsterSpine.setStartListener(trackEntry => {
	this._curTrackIndex = trackEntry.trackIndex;
});

简单的实例


export class UI_PillageLayer extends Component {
	@property(sp.Skeleton)
  spine: sp.Skeleton = null;		// skeleton组件
  
  onLoad() {
    // 设置播放速度
    this.spine.timeScale = 0.6;
    // 设置两个动画之间的混合时间
    this.spine.setMix("walk", "run", 0.2);
    // 设置当前动画播放
    this.spine.setAnimation(0, "walk", true);
    // 设置当前皮肤
    this.spine.setSkin("boy");
    // spine动画单次循环结束回调相关
    this.spine.setCompleteListener((trackEntry) => {
      let track = trackEntry.trackIndex;
      let aniName = trackEntry.animation ? trackEntry.animation.name : "";
      let loopCount = Math.floor(trackEntry.trackTime/trackEntry.animationEnd);
      if (aniName === "walk") {
        this.spine.timeScale = 1;
        this.spine.setToSetupPose();
        this.spine.setAnimation(trackIndex, "run", true);
      }
    });
  }
  
  // 更换皮肤
	public ChangeSkinEvent() {
    this.spine.setSkin("girl");
  }
}

与cocos2dx比较


cocos2d-C++提供了较为丰富的接口,支持动画的换肤,附件的切换, 关节的查找等。但cocos2d-x不支持这些,如果需要对其增加支持,需要增加了一些tolua++ 接口的设定,可参考博客:
cocosLua 之骨骼动画

cocos2dx 中针对于骨骼动画的使用, 存在着一个很严重的性能问题, 尤其多个骨骼动画存在的情况下。原因在于骨骼数据也就是.json/.skel 在解析的时候比较慢导致的。

优化的策略:C++或lua在创建骨骼动画的使用增加一个缓存管理类,如果动画没有在缓存中,则进行创建,如果存在,就直接获取数据

这种方式最好增加一个预加载的模式,缺陷就是首次加载的时候比较卡顿,但以后就好多了。

对于creator来说, 官方的大力支持及拓展,使其比cocos2d-x好很多。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鹤九日

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值