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)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章