Spine学习

最近学习了一下Spine在Unity里的应用,利用SpineDemo里的资源结合其内容简单的做了两个测试场景(见下图)。工程的github地址为:https://github.com/luckyWjr/SpineTest,有兴趣的小伙伴可以一起学习学习。

 

介绍

个人的环境是:Unity2019.3.0 和 spine-unity 3.8,同时在例子中还使用到了Input System

Spine文档:http://zh.esotericsoftware.com/spine-unity

http://zh.esotericsoftware.com/spine-using-runtimes

由于官方文档介绍的相对比较详细了,就简单的介绍下自己在制作过程中遇到的一些问题以及一些比较重要的知识点。

SkeletonAnimation

当我们把Spine导出到Unity的_SkeletonData文件拖到场景中选中SkeletonAnimation,就会生成一个GameObject来展示你的动画文件。其中有个很重要的组件,也就是SkeletonAnimation。这个组件中有几个比较重要的字段是我们之后开发会频繁使用到的:

class 获取方法 功能
Skeleton SkeletonAnim.skeleton 有状态的对象,可以设置骨架的姿势或者替换一个槽的附件等。例如可以用Skeleton.ScaleX来进行水平翻转,Skeleton.SetSkin(Skin)设置皮肤等
SkeletonData SkeletonAnim.skeleton.Data 无状态的对象,可以获得一些信息,例如Animation的持续性、Event、或者Setup/Bind姿势。例如可以用SkeletonData.FindSkin(Skin)来查找皮肤,SkeletonData.Skins获取皮肤列表,SkeletonData.Animations获取动画列表等
AnimationState SkeletonAnim.state(需要在Start之后获取) 有状态的对象,可以对Spine进行一些动画相关的操作。例如用AnimationState.TimeScale来设置播放速度,AnimationState.SetAnimation(TrackId, AnimName, IsLoop)来设置当前播放的动画,AnimationState.AddAnimation(TrackId, AnimName, IsLoop, DelayTime)来添加动画进队列等。
SkeletonDataAsset SkeletonAnim.skeletonDataAsset 无状态对象,可以获取到_SkeletonData.asset文件的信息,例如SkeletonDataAsset.scale获取到缩放比例,SkeletonDataAsset.GetSkeletonData(IsQuiet)获取SkeletonData,SkeletonDataAsset.atlasAssets[0].PrimaryMaterial获取第一个图集的Material信息等

换装相关

一些简单的功能就不赘述了,这里主要讲讲有关换装的功能

我们一共有如下两种方法可以进行换装(在SpineDisplayTest中都已实现)

1.通过更换插槽(Slot)对应的附件(Attachment)来进行换装,需要注意的是这种方法若在中途更换了皮肤(Skin)并且新的皮肤没有对应的插槽的话会出现问题。(Unity demo:Mix and Match Equip)

2.在Spine中通过设置一系列的皮肤来显示,然后通过选择不同的皮肤来换装(Spine demo:mix-and-match-pro)

首先我们讲讲第一种方法,你需要知道每件装备它要替换的是哪个插槽的附件,因此我们需要定义一些配置来对应。在Demo中,我的思路是将一个换装类型放在同一个文件夹下,例如文件夹Gun,Goggles,然后通过配置来进行关联。当然了,我们也可以和美术直接定义好名称,就不需要这些配置了。

[Serializable]
public class EquipConfig
{
    public string Type;//文件夹名称
    [SpineSlot] public string Slot;
    [SpineSkin] public string Skin;
    [SpineAttachment(skinField: "Skin")] public string Attachment;
}

然后我们需要在我们的文件夹下添加asset文件,来关联新的装备

[CreateAssetMenu(fileName = "New Equip Asset", menuName = "Spine/Equip Asset")]
public class EquipData : ScriptableObject
{
    public string Type;
    public Sprite Image;
}

例如Gun文件夹下有两个asset文件,Type都是Gun,Image分别是两个枪支图片。两者结合起来,我们就知道某张图片(也就是装备)要替换哪个插槽的附件了。然后我们可以通过下面方法得到一个新的Attachment

Attachment.GetRemappedClone (Sprite, Material, premultiplyAlpha, cloneMeshAsLinked, useOriginalRegionSize)

接着将这个Attachment设置到皮肤(Skin)中即可。注意:当Attachments更改的时候必须调用Skeleton.SetSlotsToSetupPose()方法才能使更改生效。

Skin.SetAttachment(slotIndex, attachmentName, attachment);
Skeleton.SetSkin(Skin);
Skeleton.SetSlotsToSetupPose();

第二种方法我们的工作就比较简单了,只需要美术那边都操作好,我们把需要显示的Skin通过AddAttachments方法添加进去即可。注意:由于Attachments也发生了变动,也需要调用SetSlotsToSetupPose

Skin.AddAttachments(Skin1)
...
Skin.AddAttachments(SkinN)
Skeleton.SetSkin(Skin);
Skeleton.SetSlotsToSetupPose();

AnimationState

首先讲一下关于动画分层的一些问题,可以参考demo:Object Oriented Sample。按照文档中的描述设置好动画,如下

AnimationStateSetAnimation(0, "run", true);
AnimationState.SetAnimation(1, "shoot", false);

运行后发现,当我走路的时候手是垂着的,射击之后手抬起来,但是当射击结束之后,手依旧保持着射击时的姿势,并不会变回走时的姿势。解决方法如下,我们需要在SetAnimation后Add一个空动画

AnimationState.SetAnimation(1, "shoot", false);
AnimationState.AddEmptyAnimation(1, MixDuring, MixDelay);

或者在Update中当动画完成后,将该层动画设置为空

if (TrackEntry != null && TrackEntry.IsComplete)
{
    AnimationState.SetEmptyAnimation(1, MixDuring);
    TrackEntry = null;
}

除此之外,我们还可以利用Animation的Apply方法,来使动画播放到指定时间,例如用于显示血条的百分比。参考demo:SpineGauge。

Animation.Apply (skeleton, lastTime, time, loop, events, alpha, blend, direction)

猜你喜欢

转载自blog.csdn.net/wangjiangrong/article/details/105276151