Spine渲染原理解析与源码解读

  • 安装环境
  • 从Spine编辑器导出
  • 将资源导入Unity
  • 基础概念
  • 其他相关概念
  • Spine架构
    • Spine运行时的各个模块
    • 有状态(Stateful) 和 无状态(Stateless) 数据对象
    • 源码解读
      • 1、 Slot类:存储插槽的当前姿势。
      • 2、SlotData类:slot实例里用的数据的数据格式
      • 3、BoneData类:Bone实例对应的单个骨头实例里用的数据格式
      • 4、Bone类:存储单个骨头位置等数据
      • 5、SkeletonData: Skeleton实例对应的数据格式。
      • 6、Skeleton:根据data新建Bone和Slot。
      • 11、Skin:一套皮肤下的所有attachment都在skin实例下。
      • 12、attachment目录:各种附件的处理处理方法,继承于Attachment基类。
      • 13、Texture:定义了Texture抽象类
      • 14、TextureAtlas:针对atlas文本进行解析处理,
      • 15、AnimationStateData:存储AnimationState动画更改时要应用的混合(交叉淡入淡出)持续时间。
      • 16、AnimationState:随着时间调用动画,动画入队等待播放,允许多个动画叠加。
      • 17、Animation:实现了各种timeline类。
      • 18、AssetManager:静态资源管理。
  • Spine渲染流程
  • 文章参考

安装环境

游戏引擎:Unity 2019
运行库:Unity Spine 3.8

从Spine编辑器导出

.json文件,它包含所有骨架信息。
.png文件,它包含当前版本所有图片的集合。
.atlas.txt文件,它包含打包的图集信息。

【注意】
在窗口的右下角可以看到图集扩展名标签,你应该将文本框中的.atlas设置为.atlas.txt。(如果不这么做可能会出现一些问题,因为Unity默认不会识别以.atlas后缀的文件,虽然spine-unity可以识别这个文件。不管怎么样,设置为.atlas.txt将避免大部分的问题)。

将资源导入Unity

确保Unity中已经导入Spine运行库
1)确保已经打开你的Unity项目:项目中应该已经有spine-unity运行库。
2)在文件夹中找到刚才导出的3个文件。(json, .atlas.txt and .png)
3)将3个文件(或者包含它们的文件夹)拖进Unity的Project面板。

spine-unity运行库会根据这些文件自动生成必要的Unity资源。
然后你会看到3个新文件。

_Material资源包含一个着色器引用和.png纹理。
_Atlas资源包含一个材质引用和.atlas.txt。
_SkeletonData资源包含一个json引用和_Atlas资源。

基础概念

1、骨架Skeleton:指代的是数据的集合,包含构成此骨架的所有骨骼、插槽、附件及其他信息。

2、骨骼bones:一个人物本身由多个关节的骨骼组成。除了根骨骼以外,每个骨骼都有对应的父骨骼,骨骼与骨骼之间的关系最终构造成类似树的结构。

3、插槽slot:一个骨骼bone下可能有多个slot插槽,每个slot插槽下可以放置一个附件实例。

插槽本身的存在有两个重要的意义,一个是灵活的控制渲染顺序,一个是分组同类附件。
一个插槽可以有多个附件,但一次只能看到一个。
举个简单的栗子,图中手枪所在的位置的插槽是"武器"插槽,而该插槽可以放置不同的武器附件,例如"手枪"附件或"菜刀"附件。

4、附件attachment:slot插槽内当前渲染的附件实例,即真实上屏渲染的实物素材。(可能需要对素材做旋转、偏移、缩放甚至网格化mesh处理)。

5、皮肤skin:skin可以看做是attachment的集合,或者可以认为是attachment的一个映射查询表,一个人物可以由多套skin,通过切换skin的方式去查询不同的附件映射表,便可以变相的实现人物的全身换装。

其他相关概念

关键帧
权重与网格
区域附件
点附件
网格附件
边界框附件
剪裁附件
路径附件
IK约束
变换约束
路径约束

Spine架构

Spine运行时的各个模块


1、Loading模块:是针对资源加载的处理,一个spine形象的骨架信息导出后,一般会导出为json或者二进制文件的形式,由于json形式纯文本文件过大,所以官方提供了二进制文件导出的形式,并且辅以运行库的代码针对二进制文件进行解析。
其次,Loading模块中的atlasAttachmentLoader将会负责atlas文件的解析,由于atlas文件本身是字符串的形式,内部包含雪碧图中素材的位置信息,所以需要解析后与素材建立”关联关系“。

例如:Eyes-close素材在picture1.png图片中的x,y位置 旋转角度为z,而构造出来的这种映射关系将用于被实例化attachment的时候消费。

2、Spine Texture Atlas模块:一张素材图映射一个atlasPage,一张素材图中的某个区域块映射一个atlasRegion,而region的详细绘制信息本质上已经在上个模块完成。

3、Rending模块:由渲染层遍历slot进行渲染,这里不做详解,渲染层并非spine核心库所负责的部分,上屏渲染可以由canvas、webGL或者其他第三方渲染库渲染.

例如pixijs。

4、SetupPoseData模块:或者称之为SkeletonData模块,数据源从这里输入进行处理,但是并不是最终数据,可以理解为这里对数据做了一层预处理,会将骨骼数据先处理为boneData,插槽数据处理为slotData,当然也有部分数据不需要被再次处理,在这里,也会根据前面生成的atlasRegion去构造出对应的附件实例,存储进skin中,skin本质上为附件映射表。

5、Instance Data模块:或者称之为Skeleton模块,Skeleton实例本身是渲染层上屏渲染的真实直接数据源,渲染层将读取Skeleton实例上的插槽信息,渲染对应的附件,在这里,许多数据对象已经被处理成对应的实例对象,例如boneData已经被处理为Bone实例,slotData已经被处理为Slot实例;其次,Skeleton实例中有两个比较关键的方法,updateWorldTransform和setToSetUpPose。

updateWorldTransform为更新世界变换,本质是触发骨骼位置的计算,由于骨骼位置可能发生旋转偏移,其对应的子骨骼也会受到影响,因此需要更新世界变换重新计算所有骨骼的最新坐标位置。

setToSetUpPose为更新实例到当前初始状态,一般才初始化时或重置人物状态时调用,会将人物形象骨骼装扮等切换为初始最初的状态。

6、Animation模块:动画模块被单独抽离,不仅更方便维护和更新实例的状态信息,整体架构逻辑也简洁明了,由动画state实例去触发skeleton实例的更新,接下来skeleton实例调用updateWorldTransform更新世界变化,之后重新上屏渲染。

有状态(Stateful) 和 无状态(Stateless) 数据对象

数据对象是无状态的,可在任意数量的骨架实例间共用。
有对应实例数据的数据对象类名称一般以“Data”结尾,没有对应实例数据的数据对象则没有后缀,如附件、皮肤及动画。

类似Skeleton、 Bone、 Slot、 AnimationState这些类都是有状态的对象,对它们进行修改不会影响到其它实例。你可以翻转Skeleton、复位Bone、修改Slot或者改变AnimationState的时间轴,并且它只适用于单例。

类似SkeletonData, Animation, Attachment, BoneData, SlotData这些类都是无状态的对象,设计初衷就是让他们可以被所有Skeleton实例交叉访问(比如每个Spine GameObject可以创建一个骨架)。通常,你不应该去改动这些无状态的对象。

【经验之谈】
SkeletonData是数据对象,而Skeleton是实例对象。
如果想得到有状态的对象,你可以使用Skeleton。(比如:设置骨架的姿势或者替换一个槽的附件)
如果想得到无状态的对象,你可以使用SkeletonData。(比如:想要获得一些信息,例如Animation的持续性、Event、或者Setup/Bind姿势)

源码解读

1、 Slot类:存储插槽的当前姿势。

插槽为目的组织附件,并提供存储附件状态的位置。
状态不能存储在附件本身中,因为附件是无状态的,可以跨多个骨架共享。
deform容器是存储mesh附件的处理信息。

internal SlotData data;
internal Bone bone;
internal float r, g, b, a;
internal float r2, g2, b2;
internal bool hasSecondColor;
internal Attachment attachment;
internal float attachmentTime;
internal ExposedList<float> deform = new ExposedList<float>();
internal int attachmentState;

2、SlotData类:slot实例里用的数据的数据格式

数据格式主要包含index、插槽名称、附件名称、boneData等。

internal int index;
internal string name;
internal BoneData boneData;
internal float r = 1, g = 1, b = 1, a = 1;
internal float r2 = 0, g2 = 0, b2 = 0;
internal bool hasSecondColor = false;
internal string attachmentName;
internal BlendMode blendMode;

3、BoneData类:Bone实例对应的单个骨头实例里用的数据格式

包含index(骨头也有index)、骨头名称、父骨头数据、骨头本地转换数据、世界转换的模式。

internal int index;
internal string name;
internal BoneData parent;
internal float length;
internal float x, y, rotation, scaleX = 1, scaleY = 1, shearX, shearY;
internal TransformMode transformMode = TransformMode.Normal;
internal bool skinRequired;

4、Bone类:存储单个骨头位置等数据

关键方法updateWorldTransformWith,更新骨骼的世界坐标。
包含其他的一些方法,世界坐标和本地坐标的转换,旋转转换等。

static public bool yDown;
internal BoneData data;
internal Skeleton skeleton;
internal Bone parent;
internal ExposedList<Bone> children = new ExposedList<Bone>();
internal float x, y, rotation, scaleX, scaleY, shearX, shearY;
internal float ax, ay, arotation, ascaleX, ascaleY, ashearX, ashearY;
internal bool appliedValid;
internal float a, b, worldX;
internal float c, d, worldY;
internal bool sorted, active;

5、SkeletonData: Skeleton实例对应的数据格式。

包含bones、slots、skins、events、animations、各种约束。
由于是数据对象,仅提供了一些findbone、findslot的方法。

internal string name;
internal ExposedList<BoneData> bones = new ExposedList<BoneData>(); // Ordered parents first
internal ExposedList<SlotData> slots = new ExposedList<SlotData>(); // Setup pose draw order.
internal ExposedList<Skin> skins = new ExposedList<Skin>();
internal Skin defaultSkin;
internal ExposedList<EventData> events = new ExposedList<EventData>();
internal ExposedList<Animation> animations = new ExposedList<Animation>();
internal ExposedList<IkConstraintData> ikConstraints = new ExposedList<IkConstraintData>();
internal ExposedList<TransformConstraintData> transformConstraints = new ExposedList<TransformConstraintData>();
internal ExposedList<PathConstraintData> pathConstraints = new ExposedList<PathConstraintData>();
internal float x , y, width, height;
internal string version, hash;// Nonessential.
internal float fps;
internal string imagesPath, audioPath;

6、Skeleton:根据data新建Bone和Slot。

bone有index按顺序建立关联关系。调用setToSetupPose将bone和slot设置到初始位置。会遍历调用bone和slot对应的方法。updateWorldTransform调用bone的updateWorldTransform更新骨骼位置。提供了一些Bone、slot、attachment的get、set方法。

internal SkeletonData data;
internal ExposedList<Bone> bones;
internal ExposedList<Slot> slots;
internal ExposedList<Slot> drawOrder;
internal ExposedList<IkConstraint> ikConstraints;
internal ExposedList<TransformConstraint> transformConstraints;
internal ExposedList<PathConstraint> pathConstraints;
internal ExposedList<IUpdatable> updateCache = new ExposedList<IUpdatable>();
internal ExposedList<Bone> updateCacheReset = new ExposedList<Bone>();
internal Skin skin;
internal float r = 1, g = 1, b = 1, a = 1;
internal float time;
private float scaleX = 1, scaleY = 1;
internal float x, y;

11、Skin:一套皮肤下的所有attachment都在skin实例下。

提供了操作skin和attachment的方法。这里操作的方法相当于dictionary,不是改变人物装扮的。

12、attachment目录:各种附件的处理处理方法,继承于Attachment基类。

实际由对应的AttachmentLoader调用对应的附件类方法。
AtlasAttachmentLoader实现了对应方法。

13、Texture:定义了Texture抽象类

定义一些抽象方法需要被实现。

14、TextureAtlas:针对atlas文本进行解析处理,

实现TextureAtlasReader进行逐行读取,
texture借助外部传入的textureLoader回调来获取对应的纹理。
每块小素材对应一个TextureAtlasPage,素材信息读取解析后构造对应TextureAtlasRegion。

15、AnimationStateData:存储AnimationState动画更改时要应用的混合(交叉淡入淡出)持续时间。

16、AnimationState:随着时间调用动画,动画入队等待播放,允许多个动画叠加。

分多个track存储动画、区分不同动画的timeline,针对event事件的处理逻辑等。

17、Animation:实现了各种timeline类。

Animation负责调用apply方法触发更新,其apply方法会调用各个timeline的apply方法更新。timeline类中实现找到对应关键帧 决定如何渲染。

18、AssetManager:静态资源管理。

包括拉取文本资源、拉取二进制资源、加载纹理。调用TextureAtlas处理atlas文本等。

Spine渲染流程

文章参考

链接: link1.

链接: link2.

链接: link3.

【Unity】 Spine渲染原理解析与源码解读相关推荐

  1. django middleware 中间件原理概念,源码解读分析

    用到的知识点 wsgi 搜索应用的入口 闭包,高阶函数递归调用 中间件实现的关键技术 asyncio 了解异步与同步函数类型转换 原理概念逻辑 引用官方文档 你可以把它想象成一个洋葱:每个中间件类都是 ...

  2. 【JVM】Java类加载器设计原理(ClassLoader源码解读/ SPI机制/ 绕开双亲委派/ 常见Java虚拟机)

    目录 1. 什么是类加载器 2. 类加载器加载的过程 3. Class文件读取来源 4. 类加载器的分类 5. 那些操作会初始化类加载器 6. 类加载器的双亲委派机制 6.1 双亲委派机制机制的好处 ...

  3. mysql8.0源代码解析_源码解读:MySQL 8.0 InnoDB无锁化设计的日志系统

    原标题:源码解读:MySQL 8.0 InnoDB无锁化设计的日志系统 作者介绍 张永翔,现任网易云RDS开发,持续关注MySQL及数据库运维领域,擅长MySQL运维,知乎ID:雁南归. MySQL ...

  4. Android悬浮窗原理解析(Window)[源码]

    悬浮窗,在大多数应用中还是很少见的,目前我们接触到的悬浮窗,差不多都是一些系统级的应用软件,例如:360安全卫士,腾讯手机管家等:在某些服务行业如金融,餐饮等,也会在应用中添加悬浮窗,例如:美团的偷红 ...

  5. SpringKafka原理解析及源码学习-Spring生态(一)

    Kafka 作为老牌消息中间件, 高吞吐是它的拿手好戏. Spring 的生态中也有官方提供的 spring-kafka.jar. 本文主要学习 Spring 官方提供的 spring-kafka.j ...

  6. Asp.Net Core Authorize解析(源码解读)

    一.前言 IdentityServer4已经分享了一些应用实战的文章,从架构到授权中心的落地应用,也伴随着对IdentityServer4掌握了一些使用规则,但是很多原理性东西还是一知半解,故我这里持 ...

  7. cvMorphology形态学原理解析及源码分析

    ⑴ 图像形态学处理的概念...1 ⑵ 二值图像的逻辑运算...3 ⑶ 膨胀和腐蚀...4 (4) 高级形态学变换...8 (5) 细化...10 ⑴ 图像形态学处理的概念 数字图像处理中的形态学处理是 ...

  8. mysql 一致性读_MySQL半一致性读原理解析-从源码角度解析

    1.什么是半一致性读 A type of read operation used for UPDATE statements, that is a combination of read commit ...

  9. element 往node里面增加属性值_【Vue原理】Compile - 源码版 之 Parse 属性解析

    写文章不容易,点个赞呗兄弟 专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧 研究基于 Vue版本 [2.5.17] 如果你觉得排版难 ...

最新文章

  1. Linux之nginx入门
  2. Gooogle Test中的TEST()宏代码分析
  3. linux 配置jupyter远程访问
  4. Camera360与全球1.8亿用户共同创造更美的照片
  5. iOS开发之Masonry框架-使用方法须知
  6. 此处不允许使用分组函数_查找当前薪水排名第二多的员工信息(不使用order by和窗口函数)...
  7. python bokeh_浅谈python可视化包Bokeh
  8. py-R-FCN安装记录
  9. uva_816 Abbott's Revenge(BFS求解最短路、结点状态由坐标和方向表示)
  10. 如何制定人生目标和实现目标
  11. Operator ‘==‘ cannot be applied to operands of type ‘byte[]‘ and ‘string‘
  12. Powerdesigner pdm视图看不到表注释comment问题
  13. 魔兽怀旧服务器位置,《魔兽世界》怀旧服稀有狼位置坐标大全
  14. 新疆大盘鸡的标准做法
  15. ARCGIS清晰的地图,底图,道路街景图
  16. 计算机毕业设计(附源码)python校园疫情防控管理软件
  17. 雾霾环保主题动态网站设计作业
  18. 微信5秒超时 php异步,微信公众号-5秒内不回复测试并处理方案,顺便复习php 时间执行...
  19. MFC界面控件BCGControlBar v33.3 - 可视化管理器和主题更新
  20. 鸿蒙开发(13)---ProgressBar与RoundProgressBar组件

热门文章

  1. 问题 L: Daydream
  2. MATLAB环境下基于AlexNet网络的Deep Dream图像生成
  3. HIT 软件构造 面向复用的设计模式
  4. KBP410-ASEMI研磨机专用整流桥KBP410
  5. 30多条立马执行的站内SEO优化建议
  6. apk一键脱壳工具_miui11自带应用商店apk下载-miui11自带应用商店下载最新官方版 v1.4.5...
  7. 微信8.0搞笑视频合集网盘下载 怎么设置8.0状态教程攻略分享
  8. 虚拟机创建及安装ELK
  9. esp8266-12模块 ap模式 sta模式 AT测试
  10. 超详细爬取百度贴吧(手机极速版)