http://zh.esotericsoftware.com/spine-unity#SkeletonAnimation
许可证
在购买Spine之前,个人或公司内部可以使用运行库进行评估测试。如果您希望将Spine运行库集成到您的程序中、或者在您发布的程序包中包含Spine运行库、或者修改Spine运行库,您需要一个有效的Spine license。更多的信息您可以查看Spine Runtimes Software License。 在购买Spine之后,可以在Spine Software License的第二段中详细了解Spine运行库许可证的授权方式。Spine运行库主要职责是操作从Spine中导出的数据,以及在许可证授权的范围内进行创建或者扩展。
Examples\Getting Started
文件夹,然后打开并运行Unity Scene文件,您可以在scene中看到一些提示信息,还可以查看Inspector和示例脚本的内容。在Unity中,spine-unity运行库可以加载、操作和渲染Spine骨骼动画。
在Unity中使用spine-unity可能跟别的插件结合使用。比如使用2D Toolkit的图集系统,您可以在Unity中点击Edit->Preferences->Spine,然后点击Enable。
如果您不熟悉C#编程和Unity的使用方式,我们建议您先查阅Unity官方教程。然后从Interface & Essentials和Scripting这两个主题开始。但是Unity的Animation主题并不能直接适用于spine-unity,请直接学习spine-unity。
spine-unity是在(spine-csharp)基础上构建的。
导入最新版unitypackage之后,进入Examples\Getting Started
目录。
打开并运行Unity Scene文件。 您可以在scene中看到一些提示信息,还可以查看Inspector和示例脚本的内容。
这些信息将介绍基本的姿势和角色动画。
您可以访问spine-unity论坛查阅更多信息。
Spine菜单
> 导出
(CTRL
+E
)。这会打开导出窗口。JSON
。创建图集
复选框。(推荐初学者查看非必要数据
,优质打印
)。
创建图集
复选框旁边点击设置
。然后会打开纹理打包器设置
窗口。图集扩展名
标签,你应该将文本框中的.atlas
设置为.atlas.txt
。(如果不这么做可能会出现一些问题,因为Unity默认不会识别以.atlas
后缀的文件,虽然spine-unity可以识别这个文件。不管怎么样,设置为.atlas.txt
将避免大部分的问题)。纹理打包器设置
窗口了,点击确定
关闭。导出
。
对于2D Toolkit用户,第3步(打包
.png
和.atlas.txt
)不是必须的。相反,你应该适当得在你的SkeletonDataAsset
字段中添加一个tk2dSpriteCollectionData
引用。然后在Unity中点击`Edit
->Preferences
->Spine
面板中点击Enable
启用对TK2D的支持。
着色器
引用和.png纹理。材质
引用和.atlas.txt。
Spine > Instantiate (SkeletonAnimation)
,实例化一个Spine游戏对象。
Examples\Getting Started
中的示例学习更多关于Spine游戏对象的知识。
- 资源配置手册 后期,你可以自己创建者3个文件。这种方式可以关注第3个步骤。
- 替换着色器 使用spine-unity默认的着色器(
Spine/Skeleton
或者Spine/SkeletonLit
)会使用Premultiplied Alpha的方式处理材质。这是Spine纹理打包器默认的设置。如果选择其他的着色器可能会产生意想不到的效果,你需要重新导出不使用Premultiplied Alpha的材质。您可以在Premultiply Alpha主题中获得更多信息。- 纹理大小 Unity默认会缩放过于庞大的图片。spine-unity运行库自动设置图集的最大大小为2048x2048。如果你的纹理比2048x2048还要大,这将导致图集坐标是错误的。所以请确保合理的导入设置,或者在Spine纹理打包器中减小最大页面的宽度和高度。
- 纹理压缩伪像 Unity2D项目默认将导入图片的纹理格式设置为"Sprite",当使用
Spine/Skeleton
着色器时会导致伪像。为了避免伪像,请确保纹理类型设置为"Texture"。spine-unity在自动导入时会尝试应用这些设置,但是在这个过程中会更新你的纹理,这些设置可能会恢复。
一些Spine编辑器更新时会要求你更新spine-unity运行库,所以它会读取和解析导出Spine数据的正确性。
Assets
->Improt Package
->Custom Package
的方式导入。另一种比较繁琐的方式是,你可以删除旧的版本,然后在导入新的版本。
- 如果你的源文件损坏或者替换这个方式可能不能正确工作。对于这种情况,在导入unitypackage之前你可能需要先删除旧版本。
- 许多unitypackage旧版本的spine-c#源文件都是不一样的。你或许应该在更新时删除这些旧的spine-csharp文件夹。否则它会工作不正常。
- 偶尔,一些文件会被删除或者合并。但是在导入unitypackage时并不会删除这些文件。你可以查看公告。
spine-csharp
和spine-unity
)。
spine-csharp/src
(在unitypackage中它叫做"spine-csharp")spine-unity/Assets/Gizmos
.spine-unity/Assets/spine-unity
spine-unity/Assets/Examples
(可选)
Gizmos
在Unity中是一个特殊文件。它只有放在assets根目录才能发挥作用。(例如:Assets/Gizmos
)spine-csharp
和spine-unity
可以放在任何文件夹内。- 有时候,你会复制许多文件。如果你这么做Unity会发出警告,请确保你复制以后删除旧的文件。
- 一些文件可能已经被移除或者合并。请拷贝整个文件夹并且不要删除他们。然后查看关于这方面的公告。
spine-unity是怎么组合到一起的? spine-unity的功能由以下几个组件组成:
spine-csharp是Spine运行库使用C#接口的公共核心。
你可以在Spine编辑器中看到这个公共核心包含的类型和数据结构的代码,其中包括Skeleton
, Bone
, Slot
, Skin
, Attachment
, Animation
。你可以在Spine官方文档中查看这些类型的描述。
它会将JSON(.json
)和二进制(在Unity中显示为.skel.bytes
)的骨架数据反序列化然后写进SkeletonData对象模型中。
它包含了基本的AnimationState
实现、Spine的基础、以及直接可以使用的动画控制。(更多内容请往下看)
所有的类都是在Spine
命名空间下。
spine-csharp可以让spine-unity, spine-xna and spine-monogame — 这些C#运行库共同使用的。因为spine-csharp没有使用UnityEngine的类功能,所以其它适用.NET/mono编写的Spine运行库都可以在spine-csharp基础上扩展。
为了保持老版Unity的Mono运行库和编译器,spine-csharp没有使用C#语言的最新功能。
Spine的核心类(定义在spine-csharp中)主要分为stateful-instance 和 stateless-data这两种:
类似Skeleton
、 Bone
、 Slot
、 AnimationState
这些类都是有状态的对象,对它们进行修改不会影响到其它实例。你可以翻转Skeleton
、复位Bone
、修改Slot
或者改变AnimationState
的时间轴,并且它只适用于单例。
类似SkeletonData
, Animation
, Attachment
, BoneData
, SlotData
这些类都是无状态的对象,设计初衷就是让他们可以被所有Skeleton实例交叉访问(比如每个Spine GameObject可以创建一个骨架)。通常,你不应该去改动这些无状态的对象。
经验之谈:
Skeleton
。(比如:设置骨架的姿势或者替换一个槽的附件)SkeletonData
。(比如:想要获得一些信息,例如Animation
的持续性、Event
、或者Setup/Bind姿势)
这只是最简单的设计方案。如果你是一个高级用户或者你知道运行库是如何运行的,那么你可以根据项目需要去自定义一些"无状态"的对象。
你可以在这里找到更多关于Spine核心类的信息。
spine-csharp主要使用C#语言,而spine-libgdx使用的是Java语言,然而因为C#和Java语言的语法和传统都非常相似,这里主要说一下除了语言之外的区别。
在spine-csharp中:
Dictionary
和Array
。
出于对性能的考虑,spine-csharp在经常使用的代码里用
ExposedList(T)
替代System.Collections.Generic.List(T)
。
spine-unity层是以spine-csharp为基础的,所以它被允许工作在UnityEngine
下,还会在Unity编辑器中使用inspectors和windows。
它包含Spine MonoBehaviours定义和资源文件,就像别的编辑器工具一样,为用户自动处理资源,其代码工具就像是PropertyAttributes。
spine-unity大部分的周期管理方法都依靠spine-csharp遵循的UnityEngine的生命周期和游戏循环。 但是它也包含主要的渲染代码(在.LateUpdate
中)将Spine骨架转化为可见网格。
spine-unity也在编辑器和运行时管理spine-csharp类的反序列化和实例化。
在编写脚本的时候,请注意:所有的spine-csharp都应该在Awake
中实例化。这意味着不能随意控制脚本执行顺序,不然不能保证当Awake
被调用时已经实例化骨架和动画状态。
你应该在Start
之后访问(或缓存).state
或.skeleton
引用。请查看Unity关于Awake的文档.
spine-unity还包括一些可选的功能类和工作流
SkeletonAnimator
允许用户使用Mecanim动画控制器
控制动画。 SkeletonUtility允许Spine.Bones
和UnityEngine.Transform
之间进行转换。 这可以让你控制UnityEngine.Transform
驱动Bone
,或者让GameObject
随着Bone
运动。
在spine-unity\Modules\
文件夹中还包括其它几个模块,它们都是直接可以用的,虽然都是一些简单得实现,但是只要稍加研究或修改就可以得到更高级得功能。
您可以在项目中任性得删除一些没有使用的模块,不用担心影响Spine的其他功能。注意:一些模块可能依赖其它的模块,所以在删除的时候应该一个一个得删。如果出现依赖问题,Unity会在编译之前提示警告。
一般来说,Spine.AnimationState
管理时间轨道、更新骨架、队列、分层以及混合/交叉混合动画。如果你使用过"Mecanim",Spine.AnimationState
更简单,虽然属于不可编程类,但是它足够灵活,可以作为大部分动画的基本逻辑。
但是Spine.AnimationState
是一个C#类。要在Unity使用它,有一个包含MonoBehaviour
的Spine.AnimationState
对象叫做SkeletonAnimation
。你可以在SkeletonAnimation
里面找到一个叫做state
的成员变量,它是Spine.AnimationState
对象的引用。
SkeletonAnimation
既管理更新时间,也生成Mesh对象,因为它是SkeletonRenderer
的派生类。你可以把骨架数据资源实例化成"Spine GameObject"然后挂到GameObject
上。你可以称SkeletonAnimation为Spine组件。
最开始,可以使用SkeletonAnimation
组件实例化一个GameObject
。然后可以在Inspector中的找到SkeletonAnimation
组件,然后点击Animation Name下拉框选择一个初始动画,当Scene启动时会直接运行这个动画。
可以设置Loop(循环播放),也是可以调整TimeScale(播放速度)。那些在Inspector属性会映射到.AnimationName
, .loop
and .timeScale
。
刚开始写代码的话,你可以给skeletonAnimation.AnimationName
属性赋值动画的名字来切换动画。你也可以给skeletonAnimation.loop
属性赋值为True,这样在游戏运行时你的动画会重复播放。
不比在Spine编辑对话框中设置动画的朝向(向左、向右)。SkeletonAnimation
的Skeleton
对象有FlipX(还有FlipY)的属性,你可以根据需要设置骨骼的水平镜像。
然而,如果你的角色在设计时两边朝向的动画是不一样的,你可以使用Spine的皮肤功能,一个皮肤表示向左,而另一个向右,然后再设置一个变量根据不同的朝向切换皮肤。
控制骨架的主要类是Spine.AnimationState。 SkeletonAnimation
是基于AnimationState
构建的,它的SkeletonAnimation.state
引用就是Spine.AnimationState
。它会在Awake
中初始化,所以应该在Start
或之后访问它。
AnimationState
是Spine动画状态机的基础实现。它的底层在某种层面来说只能管理:更新、队列、分层和混合/交叉混合动画(它不是Mecanim意义上的"State Machine")。
在代码中,你可以使用AnimationState
的方法来播放动画:
你可以在SkeletonDataAsset
的Inspector中找到混合/淡入淡出选项。你可以在"Default Mix"中调整同一个Track中两个动画切换时的平滑程度。你也可以在这里添加指定动画之间的平滑过度程度。
Track是把动画分层,让角色在同一时间可以播放几个Spine动画。
这在任何情况下都是有用的,比如,你的角色正在跑动,但是还想在跑动的时候拿枪进行射击。
如果你在Track 0播放一个动感,然后在Track 1中播放另一个动画,这两个动画在同时播放时可以根据各自的需要去控制结束点和是否循环。
在动画播放过程中,高层级的通道会覆盖低层级的Track:越大的通道数字就拥有越高的优先级。
调用SetAnimation
或者AddAnimation
这两个方法后,它们会返回一个TrackEntry
对象。
该对象代表一个正在播放或者排队的动画实例。它包含了动画的一些信息:已播放时间、播放速度和其它一些属性。
TrackEntry
可以让你在SetAnimation
和AddAnimation
之外控制正在播放或排队动画的播放参数。
如果你不选择保留SetAnimation和AddAnimation返回的TrackEntry
对象,你可以这样获得有效的TrackEntry
对象。
当前时间 (开始时间)
你可以从动画的任意时间点开始播放。
例如,你可以在SetAnimation
之后设置.Time
的值,让动画从指定的帧数
开始播放。但是要注意.Time
的单位是秒。因为Spine的摄影表每秒30帧,所以你需要把帧转换为秒,公式是time = (帧数/30f)
如果你这么做事为了动画事件,请确保
lastTime
和.Time
设置了一样的值。 如果lastTime
为0, 在Time0和.Time
之间的所有事件都将被捕获,并在下一个Update中增加/减少。
你也可以设置.EndTime
改变动画的结束时间点。
播放速度(TIMESCALE)
可以设置TrackEntry.TimeScale
去改变播放速度。还可以从SkeletonAnimation.timeScale
和AnimationState.timeScale
中获得最后修改的播放速度。
你可以将timeScale设置为0来暂停播放。要知道,即使你将
timeScale = 0
来暂停骨骼的运动,但是每一帧的骨骼动画仍然存在,同时你对骨骼得任何更改都将会覆盖更新。
这个简单的方法可以帮助你理解怎么跳转到指定时间点:
TRACKENTRY-特定事件.
你可以为特定动画实例订阅事件。更多信息可以查看事件文档。
Spine.Animation
对象对应于Spine中的一个单独的"动画片段"。如果在Spine中跑步动画命名为"run",你会得到一个叫做"run"的Spine.Animation
对象。
每个Spine.Animation
是Timeline
对象的集合。每个Timeline
对象是关键帧的集合,它定义了某个动画的值(缩放、旋转、位置、颜色、网格、IK、事件、绘制顺序)是怎么随时间改变的。每个Timeline
都有它自己的目的:Bone
的缩放、旋转和位置; slot
的附件和颜色; MeshAttachment
的自由变形(FFD)/网格顶点、还有骨架各个部分的绘制顺序和事件。
在Spine运行库中,使用Animation.Apply(...)
将Spine.Animation
应用在一个骨架上。这只能根据该骨架各个部分的Timeline
和关键帧来设置姿势。如果Timeline
不存在,则原动画值不会改变。如果Timeline
存在,它会覆盖之前的值。
这个就是说,如果你使用Spine.AnimationState
的Track机制同时播放两个动画,高通道的Timeline
会覆盖低通道的Timeline
,但是不会改变任何东西。
该系统允许用户组合骨架各个部分的不同动画,使它们相互独立得播放。
如果你想按照某个动画的时间点去摆姿势,可以直接调用Animation.Apply
。spine-unity运行库还有一个叫做Skeleton.PoseWithAnimation
的扩展方法,它允许你按照动画的名字去摆姿势。
其中一个参数始终是时间。该时间使用秒作为单位。如果你想按照Spine中那样摆姿势,你需要在调用Animation.Apply
或Skeleton.PoseWithAnimation
之前调用skeleton.SetToSetupPose()
。
这也意味着,如果没有自动复位逻辑,动画在连续播放的时候不一定和Spine中保持一致。相反,播放一个动画序列会导致之后的动画会继承之前动画的值和骨骼姿势。
在3.0中,Spine.AnimationState
可以让你选择性地使用自动复位逻辑句柄,或者你也可以使用原来的自由模式。
Spine.AnimationState 指定动画回掉的格式请参照C# 事件。你可以在里面找到一些处理动画播放的基础知识。
Spine.AnimationState 支持的事件:
Start
当动画开始播放,End
当动画被清除或中断,Complete
当动画完成它全部的持续时间,Event
当检测到用户自定义的事件。
警告:
永远不要在订阅
End
的方法中调用SetAnimation
。因为当一个动画被中断就会触发End
,然而SetAnimation
会打断所有现有的动画,这会引发无限递归(End->Handle->SetAnimation->End->Handle->SetAnimation),导致Unity没有响应,直到堆栈溢出。
学习更多关于Spine事件和AnimationState回调,请查看事件文档。
Tracks和TrackEntry只是Spine.AnimationState
的一部分,在Spine运行库中包括AnimationState
是为了访问更快捷。它在大部分情况下可以增加性能。 然而,spine-unity和spine-csharp即使没有AnimationState
也可以起作用。一个例子是,SkeletonAnimator
使用UnityEngine.Animator
代替Spine.AnimationState
,然后使用Mecanim去管理混合、分层和队列的数量和数据。
如果你想要用不同的方式统计你的动画,你可以根据打算如何使用它或者根据特殊情况去构建一个不一样的系统。
关于这点,研究Spine运行库官方文档会派得上用场。
一般来说,Spine的系统利用现代3D游戏引擎的优势。它的高级功能更是如此,比如FFD(自由变形)和权重。
它通过框架和引擎(3D术语)连接; 在术语中有网格和顶点、还有纹理映射和UVs。所以每个图像部分由多个三角形组成的多边形来定义,或者一个矩形由两个三角形组成。这样的引擎用于2D图形,这是不常见的。
基本理念是这样的: 你已经做了三角形网格。这是Spine骨架/模型成型的基础。 你有纹理数据。这个来自纹理图集。 你有着色器程序或者混合指令。
你把这些东西都交给游戏引擎,它再交给GPU,最后由GPU渲染。纹理映射到网格,着色器和混合模式是渲染的基础。
spine-unity使用Unity的MeshRenderer
和MeshFilter
组件,还有材质资源进行渲染。这些组件都是Unity用来渲染3D模型的。
SkeletonRenderer
类(它的基类是SkeletonAnimation
)在它的LateUpdate
方法中构建Mesh
。它生成顶点数组、顶点颜色、三角形索引和UVs,然后把这些都放进一个UnityEngine.Mesh
对象中。 MeshFilter
再去获得Mesh
,它将被MeshRenderer
使用。 MeshRenderer
会在适当的时间渲染网格,详情请见Unity’s game loop。
MeshFilter
和MeshRenderer
都有Retained ModeAPI(与Immediate Mode API截然相反); 也就是说,网格和材质对于持续可见并不需要每帧传递。这意味着,虽然SkeletonRenderer
/SkeletonAnimation
可以更新网格的每一帧,但是就算在运行时禁用更新(通过禁用SkeletonAnimation
或SkeletonRenderer
)也不会销毁现有的网格。
高级运用:骨架跳帧 这也意味着,在网格生成后,你可以控制和跳过网格更新去实现特殊的跳帧和逐步更新行为。这可以减少不太重要游戏元素的更新, 或者实现一个看起来像逐帧的动画。
spine-unity也使用材质存储信息,包括纹理、着色器和必要的材质属性。该材质通过AtlasAsset
分配。
MeshRenderer
的材质数组是由SkeletonRenderer
管理的,每一帧都取决于AtlasAssets
需要用到什么。直接修改该数组并不是Unity典型的设置方法。
你可能注意到在你的MeshRenderer
中有很多材质,特别是,比你实际设置的AtlasAsset
还要多。
如果你有一个以上的图集页是不正常的。渲染器的材质数组不能体现AtlasAsset中每一项的顺序和编号。SkeletonRenderer根据那些需要被渲染的Spine附件材质规划了一个材质数组。
如果所有附件共享一个材质,SkeletonRenderer只会把这个材质放进MeshRenderer。
如果一些附件用到了材质A和一些材质B,材质数组会根据材质的需要去排列顺序。这是基于附件绘制的顺序以及哪些附件可以在哪些材质纹理中。
如果是这样的顺序:
Attachment 来自 A
Attachment 来自 A
Attachment 来自 B
Attachment 来自 A
得到的材质数组是这样的:
Material A (第一和第二)
Material B (第三)
Material A (第四)
换句话说,有更多的附件交替来自于A和B的话,就会有更多的材质进入材质数组,在材质数组中的每一项都表示需要转换的材质。
Dragon的例子可以说明这点:
更多的材质在这个数组中,就表示会有更多的draw calls,这会对相同骨架实例化产生不好的影响。如果你只有一个这样的骨架,它可能不是拖慢速度的主要原因。
学习更多关于Spine资源的排列,请看这个页面Spine纹理打包器: 目录结构
同样的,改变MeshRenderer.material的值是没用的。
Renderer.material
属性只是渲染器生成的副本,但是它会立即被SkeletonRenderer的渲染代码给覆盖。
另一方面,Renderer.sharedMaterial
会修改原始材质。如果你使用这个材质生成更多的Spine游戏对象,对于它的修改应用会对所有的实例进行修改。
在这个例子中,Unity的Renderer.SetPropertyBlock是有用的方法。记住,SkeletonRenderer
和SkeletonAnimation
都使用MeshRenderer
。设置MeshRenderer的MaterialPropertyBlock允许你改变渲染器的属性值。
优化的注意事项
- 使用Renderer.SetPropertyBlock允许具有相同材质的渲染器去处理那些由不同的MaterialPropertyBlocks改变的材质属性。
- 当你在MaterialPropertyBlock中增加或改变一个属性值的时候,你需要调用
SetPropertyBlock
。但是你可以把MaterialPropertyBlock作为类的一部分,所以每当你想改变属性时,不必总是实例化一个新的- 如果你需要频繁设置一个属性,你可以使用静态方法:
Shader.PropertyToID(string)
去缓存一个整数ID,这个ID可以代替String,使MaterialPropertyBlock的Setter可以使用该ID去设置属性。
Spine一般使用阿尔法混合的方式去渲染你的Spine模型。
从Spine项目中绘制、上色和导出部件的时候,你导出PNG文件的像素编码格式是RGBA(红色、绿色、蓝色和阿尔法值)。在文件中,每个像素在阿尔法通道中有0-255的值,就像RGB通道一样,代表每个像素的透明度有256种层次。
这种透明与半透明在阿尔法通道中定义,展现深度/渲染顺序的经典问题。这些问题有许多不完善的解决方案,并且在我们今天的AAA游戏中也会发生一些奇怪的3D现象。
但是,在非常标准的方式中,也就是说i,像大多数2D阿尔法混合精灵渲染案例,包括Unity自己的Sprite
/SpriteRenderer
系统,spine-unity使用的渲染器,不使用3Dz-buffer和非阿尔法测试去确定哪些渲染在前,哪些渲染在后。
在一个网格中,它根据网格中三角形的顺序去渲染物体,然后绘制一个东西在另一个东西上面。该顺序是在Spine中控制槽的绘制顺序来决定的。
网格之间,spine-unity使用一些Unity的渲染顺序系统去确定 精灵/网格 应该谁上面。这是使用spine-unity标准配置的典型行为: Between meshes, spine-unity uses many of Unity’s render order systems to determine what sprite/mesh should be on top of which. Using the standard spine-unity setup, here is typical behavior for it:
在大多数情况下,你不需要也不应该去碰Material.renderQueue和着色器队列标签。
通过改变材质上的着色器,你可以选择用不同的着色器去获得不同的融合种类。怎么处理混合行为完全取决你。
Sorting Layer和Sorting Order属性其实是在SkeletonRenderer
/SkeletonAnimation
的Inspector中,实际上它只是修改了MeshRenderer
的sorting layer 和 sorting order 属性.
尽管被隐藏在MeshRenderer的Inspector中,这些属性实际上是MeshRenderer
serialized/stored的一部分,而不是SkeletonRenderer。
如果你保持所有的渲染器同样的分层和排序,他们会收到上述其他排序方案的影响。
如果队列标签页一样(如果你使用相同的材质和着色器),那么你应该根据摄像机的距离去控制Spine游戏对象的排序。
别忘了这个透视摄像机的排序模式.
有时候,你需要你的角色骑一辆自行车、举起一块石头或者拥抱一根柱子。对Spine而言,这意味着你要显示的东西,有些东西渲染在前面,有些东西渲染在后面。
在Unity中,网格是整体渲染的。那么你怎么知道哪个渲染在前面,哪个渲染在后面?
对于这个问题的答案是:可能将来会改变。
但是对于现在来说,你可以使用Spine-unity的SkeletonUtility方法调用"Submesh Renderers"。它会单独覆盖。
但基本上,它的作用是让你的SkeletonRenderer
网格根据槽(上面和下面)去拆分。这些拆分的部分会根据他们自己的GameObject
中的MeshRenderers去渲染。因为他们是单独渲染的,你可以分别设置他们的Sorting Order
。
这在任何地方都适用的实时网格渲染。当三角形被绘制时透明度就被应用了,而不是之后。
这里大概有一些解决方案,或者一些变通方案。 去玩一些你最爱的游戏吧!你可以在各种2D游戏中找到一些变通方法的例子。
Spine使用 1像素:1单位。意思是,如果你只是包含图像在你的骨架中,并且没有任何旋转和缩放,在Spine中该图像的1个像素就对应1个单位高和1个单位宽。
在Unity中,1单位:1米。这是Unity默认的物理值和约束(包括2D和3D)。对于这点,使用1像素:1单位通常不是一个好主意。反而,Unity自己的精灵默认缩放为1/100;意味着100个像素就是1个Unity的单位大小。
为了方便,当你将Spine数据带入Unity的时候,可以将缩放设置为0.01用来匹配Unity的精灵。
如果你想设置骨架的基本比例的高低,你可以在Skeleton Data Asset的Inspector中改变这个值。当你的SkeletonData
被读取时这个值是一个乘数。当SkeletonData
被加载并且在运行的时候去改变这个值是没有用的。
如果你想在游戏中动态得改变骨架的视觉比例(像球这种的),你可以设置gameObject.transform.localScale
属性的值。
访问Skeleton.FlipX
和Skeleton.FlipY
可以允许骨架的水平翻转和垂直翻转。 这通常是个好主意,这可以让骨架朝着一个方向,所以你可以在代码中控制翻转逻辑。如果没有,你可以随时增加一个额外的bool
变量用来控制和取消预期翻转的布尔逻辑.
你可能已经在Unity中学会怎么反转2D精灵,设置Transform的scale为负数,或者沿着Y轴旋转180度。 这两件事纯粹是视觉的目的。但是它们有其副作用,请记住: