CocosCreator3.8研究笔记(二十五)CocosCreator 动画系统-2d骨骼动画spine

本文主要是介绍CocosCreator3.8研究笔记(二十五)CocosCreator 动画系统-2d骨骼动画spine,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


大家都知道,在游戏中 一般用帧动画或者骨骼动画,实现 人物的行走、奔跑、攻击等动作。


帧动画,在上一篇已经做了介绍,感兴趣的朋友可以前往阅读: CocosCreator3.8研究笔记(二十四)CocosCreator 动画系统-动画编辑器实操-关键帧实现动态水印动画效果。


今天,我们主要介绍什么是骨骼动画?Spine 是什么,骨骼动画怎么制作的?怎么使用骨骼动画?

一、什么是骨骼动画?


骨骼动画是把角色的各部分身体部件图片绑定到一根根互相作用连接的“骨骼”上,通过控制这些骨骼的位置、旋转方向和放大缩小而生成的动画。


骨骼动画比帧动画要求更高的处理器性能,但它也有更多的优势:

  • 更少的美术资源: 骨骼动画的资源是一块块小的角色部件(比如:头、手、胳膊、腰等),美术再也不用提供每一帧完整的图片了,节省了资源大小。

  • 更小的体积: 帧动画需要提供每一帧图片。而骨骼动画只需要少量的图片资源,并把骨骼的动画数据保存在一个 json 文件里面(后文会提到),它所占用的空间非常小。

  • 更好的流畅性: 骨骼动画使用差值算法计算中间帧,这能让动画总是保持流畅的效果。

  • 装备附件: 图片绑定在骨骼上来实现动画。如果需要,可以方便的更换角色的装备满足不同的需求。甚至改变角色的样貌来达到动画重用的效果。

  • 不同动画可混合使用: 不同的骨骼动画可以被结合到一起。比如一个角色可以转动头部、射击并且同时也在走路。

  • 程序动画: 可以通过代码控制骨骼,比如可以实现跟随鼠标的射击,注视敌人,或者上坡时的身体前倾等效果。


二、Spine 是什么


Spine是一款针对游戏的2D骨骼动画编辑工具,它具有良好的UI设计和完整的功能,是一个比较成熟的骨骼动画编辑器。

Spine旨在提供更高效和简洁的工作流程,以创建游戏所需的动画。


使用Spine创建骨骼动画分为以下步骤:

(1)、在SETUP模式下,选中Images属性,导入所需图片资源所在文件夹。

​ 注意:路径名和资源名中不能出现中文,否则无法解析。

(2)、拖动Images下的图片到场景,对角色进行组装(把各个身体部位拼在一起),可通过Draw Order属性调整图片所在层的顺序。
(3)、创建骨骼,并绑定图片到骨骼上,要注意各骨骼的父子关系。
(4)、切换到ANIMATE模式,选中要“动”的骨骼,对其进行旋转、移动、缩放等操作,每次改动后要记得打关键帧。
(5)、在菜单栏找到Texture Packer项,对角色纹理进行打包,资源文件后缀为atlas(而非Cocos2d-x常用的plist)

​ 打包后将生成两个文件,即:png 和 atlas。

(6)、导出动画文件Json。


感兴趣的朋友,请查看官方网站教程:Spine快速入门教程。


三、Creator 编辑器中Spine 骨骼动画的使用


Creator 中的骨骼动画资源目前支持 JSON 和 二进制 两种数据格式。

Creator 中创建骨骼动画我们需要使用 Spine Skeleton 组件。

Spine Skeleton 组件支持 Spine 官方工具导出的数据格式,并对 Spine(骨骼动画)资源进行渲染和播放。


1、Spine Skeleton 组件属性说明

属性功能说明
CustomMaterial自定义材质,可用于实现溶解、外发光等渲染效果。
Color设置骨骼动画颜色
SkeletonData骨骼信息数据,拖拽 Spine 导出后的骨骼资源到该属性中
Default Skin选择默认的皮肤
Animation当前播放的动画名称
Animation Cache Mode渲染模式,包括 REALTIME(默认)、SHARED_CACHEPRIVATE_CACHE 三种。 1. REALTIME 模式,实时运算,支持 Spine 所有的功能。 2. SHARED_CACHE 模式,将骨骼动画及贴图数据进行缓存并共享,相当于预烘焙骨骼动画。拥有较高性能,但不支持动作融合和动作叠加,只支持动作开始和结束事件。至于内存方面,当创建 N(N>=3)个相同骨骼、相同动作的动画时,会呈现内存优势。N 值越大,优势越明显。综上 SHARED_CACHE 模式适用于场景动画、特效、副本怪物、NPC 等,能极大提高帧率和降低内存。 3. PRIVATE_CACHE 模式,与 SHARED_CACHE 类似,但不共享动画及贴图数据,且会占用额外的内存,仅存在性能优势,如果大量使用该模式播放动画可能会造成卡顿。若想利用缓存模式的高性能,但又存在换装需求(不能共享贴图数据)时,那么 PRIVATE_CACHE 就适合你。
Loop是否循环播放当前动画
PremultipliedAlpha图片是否启用贴图预乘,默认为 True。 当图片的透明区域出现色块时需要关闭该项,当图片的半透明区域颜色变黑时需要启用该项。
TimeScale当前骨骼中所有动画的时间缩放率
DebugSlots是否显示 Slot 的 Debug 信息
DebugBones是否显示骨骼的 Debug 信息
DebugMesh是否显示 Mesh 的 Debug 信息
UseTint是否开启染色效果,默认关闭。
Sockets用于将某些外部节点挂到指定的骨骼关节上,属性的值表示挂点的数量。
Enable Bacth是否开启 Spine 合批

2、导入骨骼动画资源

骨骼动画所需资源有:

  • .json/.skel 骨骼数据
  • .png 图集纹理
  • .txt/.atlas 图集数据

如图,这是一个飞机的骨骼动画资源:

在这里插入图片描述


我们将其导入cocos creator 资源管理器中:

在这里插入图片描述


3、创建骨骼动画


骨骼动画创建步骤:

(1)、为节点添加 Spine Skeleton 组件

层级管理器 中选中需要添加 Spine Skeleton 组件的节点**,然后点击 **属性检查器下方的 添加组件 -> Spine -> Skeleton 按钮,即可添加 Skeleton 组件到节点上。


在这里插入图片描述


在这里插入图片描述


(2)、从 资源管理器 中将骨骼动画资源拖动到 属性检查器 Spine 组件的 SkeletonData 属性中。


注意:要拖动带动作的json文件,如图:

在这里插入图片描述


(3)、在属性检查器中,根据实际情况设置animation 、animation cache 以及 loop 等属性

在这里插入图片描述


注意

(1)、当使用 Spine Skeleton 组件时,属性检查器 中 Node 组件上的 AnchorSize 属性是无效的。

(2)、Spine Skeleton 组件属于 UI 渲染组件,而 Canvas 节点是 UI 渲染的 渲染根节点,所以带有该组件的节点必须是 Canvas 节点(或者是带有 RenderRoot2D 组件的节点)的子节点才能在场景中正常显示。

(3)、当使用 Spine Skeleton 组件时,由于拥有 UseTint 属性,所以其自定义材质需要有两个颜色信息,否则 Spine 的染色效果可能会出错。


四、代码中Spine 骨骼动画的使用


1、从服务器远程加载文本格式的 Spine 资源

let comp = this.getComponent('sp.Skeleton') as sp.Skeleton;let image = "http://localhost/download/spineres/test/test.png";
let ske = "http://localhost/download/spineres/test/test.json";
let atlas = "http://localhost/download/spineres/test/test.atlas";
assetManager.loadAny([{ url: atlas, ext: '.txt' }, { url: ske, ext: '.txt' }], (error, assets) => {assetManager.loadRemote(image, (error, texture: Texture2D) => {let asset = new sp.SkeletonData();asset.skeletonJson = assets[1];asset.atlasText = assets[0];asset.textures = [texture];asset.textureNames = ['test.png'];skeleton.skeletonData = asset;});
});

2、从服务器远程加载二进制格式的 Spine 资源

let comp = this.getComponent('sp.Skeleton') as sp.Skeleton;let image = "http://localhost/download/spineres/1/test.png";
let ske = "http://localhost/download/spineres/1/test.skel";
let atlas = "http://localhost/download/spineres/1/test.atlas";
assetManager.loadAny([{ url: atlas, ext: '.txt' }, { url: ske, ext: '.bin' }], (error, assets) => {assetManager.loadRemote(image, (error, texture: Texture2D) => {let asset = new sp.SkeletonData();asset._nativeAsset = assets[1];asset.atlasText = assets[0];asset.textures = [texture];asset.textureNames = ['test.png'];asset._uuid = ske; // 可以传入任意字符串,但不能为空asset._nativeURL = ske; // 传入一个二进制路径用作 initSkeleton 时的 filePath 参数使用comp.skeletonData = asset;let ani = comp.setAnimation(0, 'walk', true);});
});

3、加载本地 Spine 资源

import { _decorator, Component, Node, loader, sp, Label } from 'cc';
const { ccclass, property } = _decorator;@ccclass('LoadSpine')
export class LoadSpine extends Component {@property({type:Label})tips:Label| null = null;isLoadedRes = false;start () {// Your initialization goes here.loader.loadRes("spine/alien/alien-pro", sp.SkeletonData, (err, spineAsset)=> {if(err) {this.tips!.string = "Failed to load asset";this.isLoadedRes = true; // AutoTest: Consider loading complete even if loading failedreturn;}let comp = this.getComponent('sp.Skeleton') as sp.Skeleton;comp.skeletonData = spineAsset!;let ani = comp.setAnimation(0, 'run', true);this.tips!.string = 'Load Success';this.isLoadedRes = true;});}// update (deltaTime: number) {//     // Your update function goes here.// }
}

4、动作控制、属性设置、事件监听

import { _decorator, CCClass, Component, sp } from "cc";
const { ccclass, property } = _decorator;@ccclass('SpineCtrl')
export default class SpineCtrl extends Component{mixTime:number= 0.2;private spine?: sp.Skeleton;private _hasStop = true;onLoad () {var spine = this.spine = this.getComponent('sp.Skeleton') as sp.Skeleton;this._setMix('walk', 'run');this._setMix('run', 'jump');this._setMix('walk', 'jump');spine.setStartListener(trackEntry => {var animationName = trackEntry.animation ? trackEntry.animation.name : "";console.log("[track %s][animation %s] start.", trackEntry.trackIndex, animationName);});spine.setInterruptListener(trackEntry => {var animationName = trackEntry.animation ? trackEntry.animation.name : "";console.log("[track %s][animation %s] interrupt.", trackEntry.trackIndex, animationName);});spine.setEndListener(trackEntry => {var animationName = trackEntry.animation ? trackEntry.animation.name : "";console.log("[track %s][animation %s] end.", trackEntry.trackIndex, animationName);});spine.setDisposeListener(trackEntry => {var animationName = trackEntry.animation ? trackEntry.animation.name : "";console.log("[track %s][animation %s] will be disposed.", trackEntry.trackIndex, animationName);});spine.setCompleteListener((trackEntry) => {var animationName = trackEntry.animation ? trackEntry.animation.name : "";if (animationName === 'shoot') {this.spine!.clearTrack(1);}var loopCount = Math.floor(trackEntry.trackTime / trackEntry.animationEnd);console.log("[track %s][animation %s] complete: %s", trackEntry.trackIndex, animationName, loopCount);});spine.setEventListener(((trackEntry:any, event:any) => {var animationName = trackEntry.animation ? trackEntry.animation.name : "";console.log("[track %s][animation %s] event: %s, %s, %s, %s", trackEntry.trackIndex, animationName, event.data.name, event.intValue, event.floatValue, event.stringValue);}) as any);this._hasStop = false;}// OPTIONStoggleDebugSlots () {this.spine!.debugSlots = !this.spine?.debugSlots;}toggleDebugBones () {this.spine!.debugBones = !this.spine?.debugBones;}toggleDebugMesh () {this.spine!.debugMesh = !this.spine?.debugMesh;}toggleUseTint () {this.spine!.useTint = !this.spine?.useTint;}toggleTimeScale () {if (this.spine!.timeScale === 1.0) {this.spine!.timeScale = 0.3;}else {this.spine!.timeScale = 1.0;}}// ANIMATIONSstop () {this.spine?.clearTrack(0);this._hasStop = true;}walk () {if (this._hasStop) {this.spine?.setToSetupPose();}this.spine?.setAnimation(0, 'walk', true);this._hasStop = false;}run () {if (this._hasStop) {this.spine?.setToSetupPose();}this.spine?.setAnimation(0, 'run', true);this._hasStop = false;}jump () {if (this._hasStop) {this.spine?.setToSetupPose();}this.spine?.setAnimation(0, 'jump', true);this._hasStop = false;}shoot () {this.spine?.setAnimation(1, 'shoot', false);}idle () {this.spine?.setToSetupPose();this.spine?.setAnimation(0, 'idle', true);}portal () {this.spine?.setToSetupPose();this.spine?.setAnimation(0, 'portal', false);}//_setMix (anim1: string, anim2: string) {this.spine?.setMix(anim1, anim2, this.mixTime);this.spine?.setMix(anim2, anim1, this.mixTime);}
}

这篇关于CocosCreator3.8研究笔记(二十五)CocosCreator 动画系统-2d骨骼动画spine的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/3244

相关文章

Linux系统之authconfig命令的使用解读

《Linux系统之authconfig命令的使用解读》authconfig是一个用于配置Linux系统身份验证和账户管理设置的命令行工具,主要用于RedHat系列的Linux发行版,它提供了一系列选项... 目录linux authconfig命令的使用基本语法常用选项示例总结Linux authconfi

Nginx配置系统服务&设置环境变量方式

《Nginx配置系统服务&设置环境变量方式》本文介绍了如何将Nginx配置为系统服务并设置环境变量,以便更方便地对Nginx进行操作,通过配置系统服务,可以使用系统命令来启动、停止或重新加载Nginx... 目录1.Nginx操作问题2.配置系统服android务3.设置环境变量总结1.Nginx操作问题

CSS3 最强二维布局系统之Grid 网格布局

《CSS3最强二维布局系统之Grid网格布局》CS3的Grid网格布局是目前最强的二维布局系统,可以同时对列和行进行处理,将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局,本文介... 深入学习 css3 目前最强大的布局系统 Grid 网格布局Grid 网格布局的基本认识Grid 网

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

在不同系统间迁移Python程序的方法与教程

《在不同系统间迁移Python程序的方法与教程》本文介绍了几种将Windows上编写的Python程序迁移到Linux服务器上的方法,包括使用虚拟环境和依赖冻结、容器化技术(如Docker)、使用An... 目录使用虚拟环境和依赖冻结1. 创建虚拟环境2. 冻结依赖使用容器化技术(如 docker)1. 创

CentOS系统Maven安装教程分享

《CentOS系统Maven安装教程分享》本文介绍了如何在CentOS系统中安装Maven,并提供了一个简单的实际应用案例,安装Maven需要先安装Java和设置环境变量,Maven可以自动管理项目的... 目录准备工作下载并安装Maven常见问题及解决方法实际应用案例总结Maven是一个流行的项目管理工具

C#实现系统信息监控与获取功能

《C#实现系统信息监控与获取功能》在C#开发的众多应用场景中,获取系统信息以及监控用户操作有着广泛的用途,比如在系统性能优化工具中,需要实时读取CPU、GPU资源信息,本文将详细介绍如何使用C#来实现... 目录前言一、C# 监控键盘1. 原理与实现思路2. 代码实现二、读取 CPU、GPU 资源信息1.

在C#中获取端口号与系统信息的高效实践

《在C#中获取端口号与系统信息的高效实践》在现代软件开发中,尤其是系统管理、运维、监控和性能优化等场景中,了解计算机硬件和网络的状态至关重要,C#作为一种广泛应用的编程语言,提供了丰富的API来帮助开... 目录引言1. 获取端口号信息1.1 获取活动的 TCP 和 UDP 连接说明:应用场景:2. 获取硬

JAVA系统中Spring Boot应用程序的配置文件application.yml使用详解

《JAVA系统中SpringBoot应用程序的配置文件application.yml使用详解》:本文主要介绍JAVA系统中SpringBoot应用程序的配置文件application.yml的... 目录文件路径文件内容解释1. Server 配置2. Spring 配置3. Logging 配置4. Ma

2.1/5.1和7.1声道系统有什么区别? 音频声道的专业知识科普

《2.1/5.1和7.1声道系统有什么区别?音频声道的专业知识科普》当设置环绕声系统时,会遇到2.1、5.1、7.1、7.1.2、9.1等数字,当一遍又一遍地看到它们时,可能想知道它们是什... 想要把智能电视自带的音响升级成专业级的家庭影院系统吗?那么你将面临一个重要的选择——使用 2.1、5.1 还是