프로그래밍/Spine2020. 4. 23. 17:52

출처 : http://ko.esotericsoftware.com/blog/Unity-Lightweight-Render-Pipeline-support

 

 스파인-유니티 런타임에서 유니티 2019의 경량 렌더 파이프라인을 지원하게 되었다는 소식을 전해드린다. 경량 렌더 파이프라인(Lightweight Render Pipeline - LWRP)는 빌드되어 있는 스크립터블 렌더 파이프라인(SRP)으로, 좀더 강력한 그래픽 효과를 위해 최적화되어 있다. 모바일 환경에서부터 하이엔드 PC, 콘솔 게임까지 전부 지원이 가능하다.

 이제 추가적인 유니티 패키지 매니저(UPM) com.esotericsoftware.spine.lwrp-shaders 를 다운로드하여, 스파인-유니티 런타임의 기능을 확장시켜 LWRP를 지원하도록 할 수 있다.

왜 패키지가 따로 분리되어 있는가?

 유니티는 많은 추가 모듈들을 새로운 유니티 패키지 매니저(UPM) 시스템 안으로 이동시켰다. 유니티의 LWRP 기반 쉐이더 파일들도 Lightweight RP라고 이름붙여진 UPM 패키지 안에서 제공되며, 유니티의 기본 제공 파일에 포함되지 않는다.

 스파인 LWRP 쉐이더를 스파인-유니티 런타임 안에 포함시키면 에러 메시지가 혼란을 야기하고, 유니티의 Lightweight RP 패키지를 설치하지 않은 프로젝트라면 추가적으로 설정이 필요해지는 등의 문제를 일으킬 수 있다. 우리는 스파인 LWRP 쉐이더를 UPM 패키지로 배포함으로써, 자동적으로 기능의 연관 문제를 해결하고 좀더 새롭게 이 기능을 사용할 수 있도록 했다. 

 장래에도, 유니티의 추가 패키지에 의존하는 다른 스파인-유니티 기능이 있을 경우, 별도의 UPM 패키지를 제공할 예정이다.

설치하기

 다운로드 페이지나 Git 저장소의 spine-unity/Modules 서브디렉토리에서 UPM 패키지를 다운로드할 수 있다. 압축을 풀거나 클로닝하여 패키지를 입수한 뒤, 아래 두 가지 방법 중의 하나로 패키지를 사용하도록 할 수 있다.

1) 프로젝트 안에 복사하기

 패키지의 컨텐츠들을 설치하고자 하는 프로젝트의 Packages 디렉토리 안에 복사해 넣는다. 유니티가 자동적으로 패키지를 로드할 것이다.

2) 패키지 매니저를 사용하기

 

 패키지 컨텐츠를 Assets 디렉토리의 바깥쪽 아무데나 원하는 곳에 복사해두고, 유니티의 패키지 매니저(Window > Package Manager)를 실행한 뒤 + 아이콘을 눌러서 복사한 package.json 파일을 선택해 불러온다.

 

 Package Manager 윈도우에 Spine Lightweight RP Shaders가 보이게 될 것이다.

 

 프로젝트 윈도우에서도 Packages 폴더 아래에 Spine Lightweight RP Shaders 항목들을 볼 수 있게 된다.

 

 만약 프로젝트 윈도우에 항목들이 나타나지 않는다면, 유니티를 종료하고 재실행해야 할 수 있다.

LWRP 샘플

 패키지는 위 GIF 이미지와 유사한 샘플 씬을 com.esotericsoftware.spine.lwrp-shaders-3.8/Examples/LWRP Shaders.unity에 포함하고 있으니 체크해 보기 바란다. 이 샘플 씬은 LWRP 쉐이더를 사용하는 방법과, 프로젝트 세팅을 변경하는 방법 등을 보여주고 있다.

사용법

 스파인-유니티 런타임에 포함되어 있는 표준 스파인 쉐이더(Skeleton Lit, Vertex Lit, Pixel Lit)는 경량 렌더 파이프라인과 호환되지 않는다. 대신에, Spine Lightweight RP shaders 패키지는 경량 렌더 파이프라인에 대응하는 새로운 3가지 쉐이더를 제공한다.

 Spine/Skeleton -> 이전의 Spine/Skeleton 쉐이더를 대신함
 Spine/Skeleton Lit -> 이전의 Spine/Skeleton Lit 쉐이더를 대신함
 Spine/Sprite -> 이전의 Spine/Sprite/Vertex Lit, Pixel Lit 쉐이더를 대신함

 이 쉐이더들은 지금까지와 마찬가지로 매터리얼의 쉐이더 메뉴에서 설정하여 사용할 수 있다.

 

 유니티 프로젝트의 Project Settings > Graphics에서 LightweightRenderPipelineAsset을 설정하는 것을 잊지 말기 바란다. 다음 GIF 예제는 파이프라인 세팅을 바꿈에 따라 실제 화면이 어떻게 변경되는지를 보여준다.

 

제약

 다른 모든 스파인 쉐이더와 마찬가지로, LWRP 쉐이더는 Linear 컬러 스페이스를 사용하면 프리멀티플라이 알파(PMA) 아틀라스 텍스처를 지원하지 않는다. 만약 Linear 컬러 스페이스를 사용하고 있다면, 아틀라스 텍스처를 익스포트할 때 Premuitiply Alpha 옵션을 꺼서 straight alpha 텍스처로 내보내야 한다. 더 자세한 정보는 다음 instructions for straight alpha export and import settings 페이지를 보기 바란다.

 현재 사용하고 있는 컬러 스페이스를 확인하려면 아래 그림과 같이 Edit > Project Settings > Player > Other Settings > Color Space 를 확인하면 된다.

 

 이 스파인-유니티 런타임 업데이트를 사용함으로써, 여러분의 게임이 좀더 멋진 애니메이션을 보여줄 수 있게 되길 바란다. 포럼에서 여러분의 의견을 공유해 주시길.

Posted by windship
프로그래밍/Spine2020. 4. 3. 18:54

 게임 그래픽 작업을 좀 밑바닥부터 해본 사람이 아니면 알 수 없는 자잘한 상식 같은 것이 있다. 예를 들면 이미지 리소스의 크기가 16픽셀을 넘으면 무조건 256픽셀이 되어야 한다거나, 이미지의 제한 색상 수가 16색을 넘으면 무조건 256색이 되어야 한다거나 뭐 그런 것들이다. 

 

 그 중에서도 이펙트나 애니메이션을 할 때 거의 반드시라고 해도 좋을 정도로 부딪치는 상식 아닌 상식이 있는데, 바로 이미지를 프로그램으로 조작할 때 이미지를 어둡게 (= 검은색 단색으로 밀기) 하는 것은 의외로 간단하지만, 반대로 밝게 (= 흰색 단색으로 밀기) 하는 것은 무척이나 어렵다는 사실이다. 

 

 언뜻 생각하면 이미지의 밝기를 그냥 밝게 올리면 되지 않나? 라고 생각할 지도 모른다. 하지만 컴퓨터 그래픽에서 밝기를 올린다는 것은 곧 그 픽셀의 원래 색깔이 된다는 뜻이다. 즉 명도 100% = 원래 픽셀이 가진 RGB값의 100%라는 의미가 된다. 

 

 이 때문에, 이미지를 원래의 밝기보다 더 올려서 흰색으로 만드는 것은 별도의 처리가 필요하게 된다. 옛날 게임들은 하드웨어나 엔진 레벨에서 별도의 처리가 들어가는게 보통이고, 요즘은 거의 쉐이더를 건드려서 이런 처리를 한다. 쉐이더를 건드릴 정도의 여력이 없는 프로젝트라면 보통은 흰색 단색의 이미지 리소스를 하나 더 만들어서 해결하곤 한다. 어느 쪽이든 간단하게는 구현되지 않는다. 이미 상용화된 게임들에서 별 생각없이 보던 흰색 단색으로 밀어서 밝음, 번쩍거림 등을 표현하는 효과는 사실 굉장히 고급 효과인 것.

 

 이전 포스트에서 언급한 건슈팅 게임에도, 이 단색 효과를 꼭 구현하고 싶었는데 찾아보니 일단 여러가지로 샘플이나 방법 자체는 마련이 되어 있었다. 그러나 막상 실제 게임에 반영해 보니 역시나 간단하게는 되지 않는다. 유니티나 프로그래밍에 대해 전혀 지식이 없던 나는 일단 개념을 잡는 것부터가 어려웠는데, 유니티는 일단 이미지를 표시하려면 매터리얼 설정이 있고 그 매터리얼에서 사용하는 쉐이더가 설정되어야 한다. 보통 이미지를 넣을 때는 이런게 대충 자동으로 되니까 별로 의식을 안하게 되지만 실제의 구조는 그런 식이다.

 

 이 때문에 대부분의 샘플 코드나 예제에서는 이 흰색 단색화를 구현할 때 매터리얼의 쉐이더를 조작한다. 이것저것 샘플과 웹을 뒤지고 나서 겨우 대강 윤곽이 잡히기 시작했는데, 매터리얼에서 사용하고 있는 쉐이더의 각종 속성치를 MaterialPropertyBlock이라는 놈을 통해서 조작할 수 있고 이걸 조작하면 해당 오브젝트의 MeshRenderer를 통해 반영되는 식인 듯.

 

 대충 구현에 꼭 필요한 부분의 코드를 기록해 둔다.

 

MaterialPropertyBlock 변수A;

 

void Start()
{
    변수A = new MaterialPropertyBlock();
}

 

void Update()

{

    변수A.SetColor("_FillColor", 색상); //<- 단색화할 색상을 지정함

    변수A.SetFloat("_FillPhase", 1f); //<- 색상의 농도를 지정함
    스파인이들어있는게임오브젝트.GetComponent<MeshRenderer>().SetPropertyBlock(변수A); //<- 스파인이 자식이나 부모 오브젝트에 있을 때는 게임오브젝트명을 적절하게 변경해줘야 한다

}

 

 주의해야 할 점은 해당 스파인 오브젝트는 매터리얼의 쉐이더를 SkeletonFill로 바꿔줘야 이게 먹힌다는 것. SkeletonFill.shader를 열어서 안을 보면 위쪽에 이하와 같은 구문들이 보일 것이다.

 

Shader "Spine/Skeleton Fill" {

Properties {

_FillColor ("FillColor", Color) = (1,1,1,1)

_FillPhase ("FillPhase", Range(0, 1)) = 0

 

 바로 이 부분의 _FillColor와 _FillPhase가 위 스크립트 코드의 변수A.SetColor("_FillColor", 색상), 변수A.SetFloat("_FillPhase", 1f)에 대응하게 된다. 따라서 쉐이더를 잘못 고르면 이 부분의 프로퍼티 명칭이 안 맞아 원하는 효과를 내지 못하게 된다. 특히 웹에 있는 샘플 코드는(스파인 공식 포럼의 자료 대부분 역시도) _FillPhase가 _FillAlpha로 되어 있는 경우가 많아서 이 부분을 체크하지 않으면 어디가 잘못됐는지 몰라 한참 삽질하게 된다(경험담).

 

 구현된 결과는 다음과 같다.

 

Posted by windship
프로그래밍/Spine2017. 1. 30. 13:43

(출처 : http://ko.esotericsoftware.com/spine-unity#Controlling-Animation)



Controlling Animation

애니메이션 제어하기




SkeletonAnimation


 Normally, Spine.AnimationState manages keeping track of time, updating the skeleton, queueing, layering and mixing/crossfading animation. If you're used to "Mecanim" as having State Machines, Spine.AnimationState is a simpler, non-programmable kind, but flexible enough to serve as the base for most animation logic.

 일반적으로 Spine.AnimationState 는 타임트랙 유지, 스켈레톤 갱신, 큐, 레이어링, 애니메이션의 믹싱/크로스페이딩을 관리하게 된다. 만약 당신이 상태 관리를 위해서 "메카님"을 사용하는 데에 익숙하다면, Spine.AnimationState 가 더 간단하고 프로그램을 잘 모르는 사람도 사용하기 쉬우면서도 대부분의 애니메이션 로직에 대응하기에 충분한 유연성을 제공할 수 있다.


 But Spine.AnimationState is a C# class. To make it usable in Unity, the Spine.AnimationState object is wrapped in a MonoBehaviour called SkeletonAnimation. You will find that SkeletonAnimation has a member field called state, a reference to the Spine.AnimationState object.

 하지만 Spine.AnimationState 는 C# 클래스이므로, 유니티에서 사용하려면 Spine.AnimationState 를 MonoBehaviour에서 SkeletonAnimation 이라는 이름으로 사용해야 한다. 


 SkeletonAnimation both manages the timing of the updates (through Update) and generates the Mesh object since it derives from the SkeletonRenderer class. This is the main component that's added to the GameObject when you Instantiate a Skeleton Data Asset into a "Spine GameObject". You could say that SkeletonAnimation is the Spine component.

 SkeletonAnimation 은 SkeletonRenderer 클래스에서 받아와 메쉬 오브젝트를 생성하고 Update를 통해 타이밍을 관리한다. 이것은 유니티에서 Spine GameObject를 사용해 Skeleton Data Asset 을 생성했을 때 자동으로 만들어진다. SkeletonAnimation 은 곧 스파인 컴포넌트라고 생각해도 좋다.


How to use SkeletonAnimation

SkeletonAnimation 사용하기


For Beginners

당신이 초심자라면


 “Out of the box”, an instantiated GameObject with a SkeletonAnimation component on it is ready to go. Changing the Animation dropdown in the Inspector allows you to set the initial animation for that SkeletonAnimation object which starts playing immediately when the scene starts.

 SkeletonAnimation 컴포넌트로 만들어진 GameObject만 있으면 준비는 된 것이다. 인스펙터에서 애니메이션을 변경하면 SkeletonAnimation 에 초기 애니메이션을 설정해줄 수 있다. 프로그램이 실행되고 씬이 동작하면 즉시 이 애니메이션이 돌아가게 된다.


 Looping can be enabled and disabled, and the Time Scale can be changed. These Inspector properties map to .AnimationName, .loop and .timeScale.

 계속 반복되는가의 여부와 타임스케일(빠르기)도 설정해줄 수 있다. 이것은 코드에서 .AnimationName / .loop / .timeScale 을 통해 읽어들여 사용할 수 있다.


 For beginner code, you can use skeletonAnimation.AnimationName property to change the playing animation with its name. It will start playing and loop if the skeletonAnimation.loop was set to true at the time it was changed.

 초심자 코드라면, skeletonAnimation.AnimationName 프로퍼티를 사용해 재생될 애니메이션을 변경할 수 있다. 재생이 시작되고 skeletonAnimation.loop가 true로 설정되면 계속 반복 재생될 것이다.


skeletonAnimation.timeScale = 1.5f;

skeletonAnimation.loop = true;

skeletonAnimation.AnimationName = "run";



Left and Right Animations

좌우 이동 애니메이션


 It is not necessary for you to animate left-facing and right-facing animations in Spine editor. SkeletonAnimation's Skeleton object has a FlipX property (and FlipY) you can set which horizontally flips the rendering and logical positions of bones of that skeleton.

 당신이 스파인 애니메이터에서 좌우 각각의 애니메이션을 따로 만들어야 할 필요는 없다. SkeletonAnimation 의 Skeleton 오브젝트는 FlipX와 FlipY 프로퍼티를 가지고 있어서 본의 위치와 렌더링 포지션을 뒤집어 출력시킬 수 있다.


// If your character was facing right, this will cause it to face left.

// 만약 캐릭터가 오른쪽을 보고 있다면, 이 코드는 왼쪽을 보게 만들어준다.


skeletonAnimation.skeleton.FlipX = true;


 However, if you opted to design your character asymmetrically but the movement is essentially the same in both directions, you can use Spine's Skins feature to have two skins— one facing right, and one facing left— and switch between those two as your character faces left and right.

 하지만, 당신이 캐릭터의 좌우 그래픽을 다른 형태로 디자인했다면, 스파인의 스킨 기능을 써서 좌우 두가지 모습을 만들고 캐릭터가 좌/우로 움직일 때 각각 다른 스킨을 바꿔가며 보이게 할 수 있다.


bool facingLeft = (facing != "right"); 

skeletonAnimation.skeleton.FlipX = facingLeft;

skeletonAnimation.skeleton.SetSkin(facingLeft ? "leftSkin" : "rightSkin");


For Typical Use

전형적인 사용법


 The class that actually controls the animation of the skeleton is Spine.AnimationState. SkeletonAnimation is built around AnimationState. It stores a reference to its instance of Spine.AnimationState in SkeletonAnimation.state. This is instantiated on Awake so make sure to only access it on Start or any time after.

 스켈레톤의 애니메이션을 실질적으로 컨트롤하는 클래스는 Spine.AnimationState 이다. SkeletonAnimation 은 AnimationState를 포괄하도록 만들어졌으며, SkeletonAnimation.state 안에 Spine.AnimationState의 인스턴스를 참조하여 저장한다. 이것은 Awake를 사용해서 생성할 수 있고 Start로 시작시에 부르거나 이후 언제든지 불러올 수 있다.


 AnimationState is Spine’s common-case implementation of a Spine Animation State Machine. It is lower-level in a sense that it only manages updating, queuing, layering and mixing/crossfading animations. (It is not a "State Machine" in the Mecanim sense).

 AnimationState 는 스파인의 일반적인 삽입 방식이다. 메카님을 작업할 때의 "스테이트 머신"이 아니다. 좀 더 로우레벨이고 업데이트, 큐잉, 레이어링, 믹싱, 크로스페이딩만을 관리한다.


 In code, you can play animations through AnimationState methods:

 코드에서는 AnimationState 메소드로 애니메이션을 플레이할 수 있다.


// Plays the animation named “stand” once on Track 0.

// 애니메이션 "stand"를 트랙 0에 할당하고 한번만 재생한다.


skeletonAnimation.state.SetAnimation(0, “stand”, false);


// Queues the animation named “run” to loop on Track 0 after the last animation is done.

// 애니메이션 "run"을 마지막 애니메이션 뒤에 트랙 0으로 반복 재생하도록 큐잉한다.


skeletonAnimation.state.AddAnimation(0, “run”, true, 0f);


 Mixing/crossfading options can be found on your SkeletonDataAsset's inspector. There you'll find a field for "Default Mix" which is the default duration of a mix between two animations on the same track. You may also define specific mix durations for specific pairs of animations there.

 믹싱/크로스페이딩 옵션은 SkeletonDataAsset 의 인스펙터에 있다. Default Mix 라는 필드가 있는데 이것은 하나의 트랙을 사용하는 두 개의 애니메이션 간의 믹스 수치를 결정하는 것이다. 특정 애니메이션 간에 임의의 믹스 타이밍을 주고 싶다면 이 수치를 조절해야 할 수 있다.



TRACKS

트랙


 Tracks are animation layers, for playing more than one Spine animation at once.

 트랙이란 동시에 재생되는 1개 이상의 스파인 애니메이션을 위한 레이어와 같은 개념이다.


 This is useful for when, for example, you have an animation for a character's body running, but also have an  animation for the arm shooting a gun.

 이것은 예를 들면 하나의 캐릭터가 다리는 달리고 팔은 총을 쏘는 두 개의 애니메이션을 가지고 있을 때에 유용하다.


 If you play an animation on track 0, and another animation on track 1, both animations will play at the same time and end or loop according to their own durations independently.

 만약 한 애니메이션을 트랙 0에서 재생하고 다른 애니메이션을 트랙 1에서 재생한다면, 각각의 애니메이션은 함께 재생되면서 각각 애니에 설정된 대로 끝나거나 반복된다.


 The animations keys of the animation playing on the higher track will override the keys of the lower track: higher track number, higher priority.

 두 애니메이션이 같은 부분의 키를 가지고 있을 경우, 더 높은 트랙의 키가 낮은 트랙의 키를 덮어버린다. 즉 높은 트랙이 높은 우선권을 가진다.


// Play a running animation on track 0, and a shooting animation on track 1.

// 트랙 0에서 달리는 애니, 트랙 1에서 총을 쏘는 애니메이션을 재생


skeletonAnimation.state.SetAnimation(0, "run", true);

skeletonAnimation.state.SetAnimation(1, "shoot", false);



TRACKENTRY

트랙 엔트리


 When you call SetAnimation or AddAnimation, it returns a TrackEntry object.

 SetAnimation이나 AddAnimation을 호출했을 경우, TrackEntry 오브젝트가 리턴된다.


 This object represents the instance of an animation playback for the animation you just played or queued. It holds information about what animation it is, its elapsed time, its own timescale and several other properties.

 이 오브젝트는 방금 플레이했거나 큐된 애니메이션의 인스턴스를 되돌려준다. 여기에는 어떤 애니메이션인가, 걸린 시간은 얼마인가, 타임스케일 크기, 그리고 몇 가지 다른 프로퍼티가 들어있다.


 TrackEntry lets you control the state of a playing or queued animation, and playback parameters not included in SetAnimation and AddAnimation.

 TrackEntry는 재생중이거나 큐된 애니메이션의 상태를 컨트롤할 수 있게 해주고, SetAnimation과 AddAnimation에 포함되지 않은 파라미터를 플레이백한다.


 If you choose not to keep the reference to the TrackEntry object when you called SetAnimation or AddAnimation, you can get the currently active TrackEntry by calling

 당신이 SetAnimation이나 AddAnimation을 호출했을 때 TrackEntry 오브젝트에의 참조를 보관하지 않기로 했다면, 다음을 호출해서 현재 활성화된 TrackEntry를 얻어올 수 있다.


   var trackEntry = skeletonAnimation.state.GetCurrent(myTrackNumber); 

   // null if no animation is playing.

   // 만약 아무 애니도 재생되지 않고 있다면 null이 리턴된다.   


   

CURRENT TIME (OR START TIME)

현재 시간(혹은 시작 시간)


 The time the Animation is currently playing at can be changed at any point while it's playing.

 현재 재생중인 애니메이션의 시간은 재생되고 있는 중에 언제든지 바뀔 수 있다.


 For example, you can change the .Time immediately after SetAnimation so the animation starts in the middle instead of the beginning. Note that time is in seconds. To convert Spine editor frames to seconds, you must divide by the dopesheet’s 30 fps tick marks: time = (frameNumber/30f).

 예를 들어, SetAnimation 이후 .Time을 즉시 바꿀 수 있고 그러면 시작지점 대신에 중간에서 애니메이션을 스타트시킬 수 있다. 이 시간이 초 단위라는 것을 기억하자. 스파인 에디터의 프레임을 초로 환산하려면, 타임 도프시트의 수치를 30으로 나눠야 한다.


    // Play a "dance" animation starting from frame 10

    // "dance" 애니메이션을 10프레임부터 재생

    var trackEntry = skeletonAnimation.state.SetAnimation(0, "dance", false);

    trackEntry.Time = 10f/30f;


    // You can shorten the above code this way if you only need

    // to change one field, and don't need to store the trackEntry.

    // 만약 필드 하나만 바꿀 것이고 트랙 엔트리를 보존할 필요가 없다면 코드를 아래와 같이 더 줄일 수 있다.

    skeletonAnimation.state.SetAnimation(0, "dance", false).Time = 10f/30f;


 If you are doing this to Animations with animation events, make sure you also set lastTime to the same value as well. If lastTime is left as 0, all events between time 0 and time will be captured and raised/fired in the next Update.

 만약 이것을 애니메이션 이벤트와 함께 하려면, lastTime을 같은 값으로 해 줘야 한다. 만약 lastTime이 0이 되어버리면, 0에서부터 time까지 사이에 있는 모든 이벤트가 캡처되고 다음 Update 때 나와버릴 것이다.


 You can also change the point where the animation ends by setting .EndTime.

 .EndTime을 설정해서 애니메이션이 언제 끝날 것인지도 정해줄 수 있다.



TIMESCALE

타임스케일


 You can change the playback speed by setting that TrackEntry’s .TimeScale. This gets multiplied by the SkeletonAnimation.timeScale and AnimationState.timeScale to get the final timescale.

 트랙엔트리의 .TimeScale을 설정해서 애니메이션의 재생 속도를 바꿀 수 있다. 


 You can set timeScale to 0 so it pauses. Note that even if timeScale = 0 results in the skeleton not moving, the animation is still be applied to the skeleton every frame. Any changes you make to the skeleton will still be overridden in the normal updates. Here is a sample helper method if you want to jump to a certain point in time.

 timeScale 을 0으로 설정해서 애니메이션을 일시 정지시킬 수 있다. timeScale을 0으로 하는 순간 스켈레톤은 움직이지 않지만, 매 프레임 애니메이션은 계속 적용되고 있다는 점을 기억하자.  스켈레톤에 가해지는 변형은 계속 업데이트되고 있을 것이다.


static public Spine.TrackEntry JumpToTime (SkeletonAnimation skeletonAnimation, int trackNumber, float time, bool skipEvents, bool stop) {

    if (skeletonAnimation == null) return null;

    return JumpToTime(skeletonAnimation.state.GetCurrent(trackNumber), time, skipEvents, stop);

}


static public Spine.TrackEntry JumpToTime (Spine.TrackEntry trackEntry, float time, bool skipEvents, bool stop) {

   if (trackEntry != null) {

      trackEntry.time = time;

      if (skipEvents)

         trackEntry.lastTime = time;   // in pre-3.0. This ignores attachment keys too.

         // 3.0 이전 버전에서는 이 부분이 어태치먼트 키도 무시하게 된다.


      if (stop)

         trackEntry.timeScale = 0;

   }

   return trackEntry;

}



TRACKENTRY-SPECIFIC EVENTS.

트랙 엔트리 - 특정 이벤트


 You can subscribe to events just for that specific animation playback instance. See the list of events here: Events Documentation.

 특정한 애니메이션 재생을 위해서 이벤트를 사용할 수 있다. Events Documentation 에서 어떤 이벤트들이 있는지 확인해보자.




Spine.Animation


 A Spine.Animation object corresponds to an individual "animation clip" animated in Spine. If a run animation called "run" was animated in Spine, you'll get a Spine.Animation object named "run".

 Spine.Animation 오브젝트는 스파인에서 재생되는 개별 "애니메이션 클립"에 대응한다. "run"이라는 애니가 스파인에서 재생되었다면, "run"이라는 이름의 Spine.Animation 오브젝트를 얻을 수 있다.


 Each Spine.Animation is a collection of Timeline objects. Each Timeline object is a collection of keys, which defines how a certain animatable value (scale, rotation, position, color, attachment, mesh vertices, IK, events, draw order) changes over time. Each Timeline has its own target: a Bone for scale, rotation and position; a slot for attachments and colors; a MeshAttachment for mesh deformation, and the appropriate parts of the skeleton for draw order and events.

 각각의 Spine.Animation 은 타임라인 오브젝트의 집합이다. 각각의 타임라인 오브젝트는 매 시간 변화하는 애니메이션 값들(스케일, 회전, 위치, 컬러, 어태치먼트, 메쉬 버텍스, IK, 이벤트, 드로우오더)를 정의하는 키 값들의 집합이다. 각각의 타임라인은 대상 타겟을 가지고 있다. 스케일과 회전, 위치는 Bone, 컬러는 Slot, 메쉬 변형치와 드로우 오더, 이벤트는 MeshAttachment이다.


 In Spine runtimes, a Spine.Animation is applied to a skeleton with Animation.Apply(...). This poses the Skeleton's various parts only according to that Animation's Timelines and keys. If a Timeline isn't there, the animatable value won't change. If a Timeline is there, it will overwrite whatever value is there with a new value.

 스파인 런타임에서 Spine.Animation은 Animation.Apply(...) 와 함께 스켈레톤에 적용된다. 이것은 스켈레톤의 여러 가지 파츠들을 애니메이션의 타임라인과 키에 따라 움직여서 애니메이션을 만들어 낸다. 


 This means that if you play two Animations at the same time using Spine.AnimationState's track system, the Timelines of the higher track will overwrite any changes that the lower track applied, but will not modify anything else.

 이는 Spine.AnimationState의 트랙 시스템을 사용해 2개의 애니메이션을 함께 재생할 때, 높은 트랙의 타임라인이 낮은 트랙에 덮어씌워진다는 것을 의미한다. 


 This system allows the user to combine different animations for different parts of the skeleton and play them back independently of each other.

 이것은 스켈레톤의 각각 다른 파츠를 움직이는 별개의 애니메이션을 유저가 조합할 수 있도록 해 준다.



Posing the Skeleton according to an animation frame/time.

애니메이션 프레임 / 시간에 의해 스켈레톤 움직이기


 You can call Animation.Apply directly if you want to pose a skeleton according to a certain point in time in that Animation. The Spine-Unity runtime also has a Skeleton.PoseWithAnimation extension method that allows you to do this according to an animation's name.

 애니메이션의 특정 지점의 스켈레톤 포즈를 바로 취하는 데에 Animation.Apply 를 호출할 수 있다. 스파인-유니티 런타임도 Skeleton.PoseWithAnimation 확장 메소드를 가지고 있어서 애니메이션 이름을 이용해 원하는 포즈를 찾을 수 있다.


 One of the parameters is always time. This is time in seconds. If you want to pose the skeleton according to what you see in the editor, you may need to call skeleton.SetToSetupPose() before calling Animation.Apply or Skeleton.PoseWithAnimation

 파라미터 중의 하나는 항상 초 단위의 시간 값을 가진다. 에디터에서 보이는 대로 스켈레톤을 움직이고 싶다면, Animation.Apply 나 Skeleton.PoseWithAnimation을 호출하기 전에 skeleton.SetToSetupPose 를 호출해야 한다.



One Animation After Another (pre-3.0)

하나의 애니메이션 직후에 다른 애니메이션 재생 (3.0 이전 버전)


 This also means that without auto-reset logic, playing animations one after another will not necessarily cause it to look like what the animations like in Spine editor. Instead, playing a sequence of animations will result in later animations inheriting the values and bone poses of the previous animation.

 이것은 자동 리셋 로직 없이, 하나의 애니메이션이 끝난 직후 다른 애니메이션을 재생할 때 스파인 에디터에서 보이는 것처럼 바로 리셋이 되도록 하는 것을 말한다. 이것이 없으면 이전 애니메이션의 키 값이 남아서 다음 애니메이션에 영향을 끼쳐 버리기 때문이다.


 In 3.0, Spine.AnimationState will handle auto-reset logic itself and give you the option to use it so it can behave like it does in Spine editor, or if you want the original free-rein mode for advanced uses.

 3.0에서는, Spine.AnimationState 가 오토 리셋 로직을 자체적으로 관리하고 스파인 에디터에서처럼 자동으로 초기화될지, 아니면 보다 고급 사용을 위해 이전 애니메이션 키값을 남길지 선택할 수 있게 해준다. 



Animation Callbacks + Spine Events

애니메이션 콜백 + 스파인 이벤트


 Spine.AnimationState provides animation callbacks in the form of C# events. You can use these to handle some basic points of animation playback.

 Spine.AnimationState 는 C#의 이벤트 형식으로 애니메이션 콜백을 제공한다. 이것을 이용해 애니메이션 재생의 기본적인 포인트를 제어할 수 있다.


 Spine.AnimationState raises events:

 Spine.AnimationState 가 발생시키는 이벤트는 다음과 같다:


Start when an animation starts playing, 

Start : 애니메이션이 언제 재생을 시작하는가

End when an animation is cleared or interrupted,

End : 애니메이션이 언제 중단 혹은 취소되는가

Complete when an animation completes its full duration,

Complete : 애니메이션이 언제 완료되는가

Event when a user-defined event is detected.

Event : 사용자가 정의한 이벤트가 감지되었을 때



WARNING:

주의 : 


 NEVER subscribe to End with a method that calls SetAnimation. Since End is raised when an animation is interrupted, and SetAnimation interrupts any existing animation, this will cause an infinite recursion of End->Handle>SetAnimation->End->Handle->SetAnimation, causing Unity to freeze until a stack overflow happens.

To learn more about Spine Events and AnimationState callbacks, see the Events documentation.

 End 이벤트는 SetAnimation을 호출하는 메소드로 사용하지 말 것. 애니메이션이 중단됐을 때 End가 걸리고, SetAnimation 이 모든 존재하는 애니메이션을 멈춰 버리며, End->Handle>SetAnimation->End->Handle->SetAnimation 식의 무한 루프가 걸리게 된다. 이렇게 되면 유니티 자체가 뻗어서 스택 오버플로우 에러가 날 때까지 멈춰버리게 된다.



Advanced Animation Control

고급 애니메이션 컨트롤


 Tracks and TrackEntry are just part of Spine.AnimationState, and AnimationState is included with the Spine runtimes just to get you going immediately. It's usable in most cases and performant for production. However, Spine-Unity and Spine-C# can function even without AnimationState. For example, SkeletonAnimator uses UnityEngine.Animator instead of Spine.AnimationState and uses Mecanim to manage numbers and data for mixing, layering and queueing.

 트랙과 트랙엔트리는 Spine.AnimationState 의 일부일 뿐이며, AnimationState 는 바로 사용할 수 있도록 스파인 런타임 안에 포함되어 있다.  이것은 대부분의 경우에 유용하지만, 스파인-유니티와 스파인-C#은 AnimationState 없이도 애니메이션을 제어할 수 있다. 예를 들어, SkeletonAnimator는 Spine.AnimationState 대신에 UnityEngine.Animator 를 사용하고 데이터의 믹싱, 레이어링, 큐잉과 애니메이션 번호 관리를 위해서 메카님을 사용한다.


 If you wanted to do bookkeeping of your animations a different way, whether to be optimized based on how you plan to use it, or to handle special cases just the way you want them, you can build a different system.

 만약 애니메이션을 다른 방식으로 다루고 싶다면 다른 방식으로 시스템을 만들어야 한다.


 In this case, studying the Official Spine Documentation will come in handy.

 이런 경우라면, 공식 스파인 문서를 좀 더 자세히 연구하는 것이 좋을 것이다.

Posted by windship
프로그래밍/Spine2017. 1. 29. 18:29

(출처 : http://blog.naver.com/ateliersera/220663775981)


* GroundConstraint *

스파인 캐릭터의 특정 본에 접근해서 제어를 하고싶다면, 해당 본 데이터를 꺼내야 합니다.


일단 모델이 있어야 하니, 뷰어 상에 Skelecton Animation 을 하나 생성 해서 제어 하고자 하는 Skelecton Data Asset을 연결시켜 줍니다.

여기에서는 기본적으로 제공하는 raptor_SkeletonData 를 이용하였습니다.



약간의 손질이 필요합니다. 포함중인 본 데이터를 제어할 수 있게 밖으로 꺼내야 하기에, Skelecton Utility Bone 스크립트를 사용합니다. 

Add Skelecton Utility를 눌러주면 생성되는 Skeleton Utility 스크립트의 BoneRoot에 위에서 만들어 놓은 testroot를 끌어다가 놓으면 사용할 수 있게 됩니다.


여기에는 바닥에 발을 붙이기 위한 스크립트를 사용 하였지만, 벽에 손을 붙인다거나 , 사다리를 팔 다리로 잡는 등의 액션을 한다면(어쌔신 크리드!?) 위의 스크립트와는 좀 더 다른 스크립트를 만들어서 써 줘야 합니다. 



* Skin 변경 방법 * 

튜토리얼에서는 Gobline이 남/녀 고블린으로의 스킨 변경 예제로 사용되어 있습니다.  

goblins 를 보면, 내부적으로 이미지 폴더 아래에 goblin 과 goblingirl 이라는 폴더가 있는데, 해당 폴더 내에는 동일한 이름의 이미지들이 들어가 있습니다.

실제로 root에서 바인딩 된 이미지를 보면 스킨 플레이스 홀더 라는 조각퍼즐 같은 부분 아래에 이미지가 위치해 있음을 알 수 있습니다.

 

이런 구조 입니다.  위에 이미지에서 right hand 부분에서 +새로만들기 버튼을 누른 후, 플레이스 홀더를 생성 하고, 그 아래쪽에 사용할 이미지를 넣으면 됩니다.

공용으로 사용하는 무기나 악세사리의 경우, 폴더 내부에 두지 말고, 그냥 이미지 아래에 둡니다. 공용 이미지는 플레이스 홀더를 사용하지 않습니다.



public void OnMouseDown () { // 마우스 클릭으로 스킨이 변경됩니다.

skeletonAnimation.skeleton.SetSkin(girlSkin ? "goblin" : "goblingirl"); //SetSkin이 스킨 변경 함수 입니다.  여기에 이름이 곧 이미지 폴더!

skeletonAnimation.skeleton.SetSlotsToSetupPose(); 

girlSkin = !girlSkin; //bool부호 값입니다. 

if (girlSkin) { 

skeletonAnimation.skeleton.SetAttachment("right hand item", null);

skeletonAnimation.skeleton.SetAttachment("left hand item", "spear");   //왼손의 아이템을 창으로 바꿉니다.

} else

skeletonAnimation.skeleton.SetAttachment("left hand item", "dagger"); // 왼손의 아이템을 단검으로 바꿉니다. 

}


skeletonAnimation.skeleton.SetSkin()을 통해 변경 합니다. Setskin("스킨 이름")으로 들어가는데, 여기에서는 간단하게 아닌지 맞는지로만 선택되게 되어있습니다.

일반 사용방법은 그냥 이름 스트링을 넣어주면 됩니다.



*지원하는 쉐이더 *

 


SPine 라는 카테고리 내의 쉐이더들 입니다. 

Bones : 가장 기본적인 Unlit 쉐이더 입니다. 라이팅을 받지 않습니다. 바리에이션이 2종류로 가장 가벼운 쉐이더중 하나 입니다. OpenGL과 Dx9 를 지원합니다.

HiddenPass : 그냥 렌더링이 안됩니다;;보이지 않아요...


Skeleton : 그림자를 적용 시킵니다. 디렉션 라이트에 영향을 받아서 그림자를 생성 합니다. 

Skeleton Lit : 그림자 적용도 되고, 스프라이트 이미지도 라이트에 영향을 받게 됩니다.

SkeletonGhost : 유령 만들때 쓰라는 걸까요??? 좀 애매한 쉐이더이긴 한데, MainColor 의 알파 값이 적용 됩니다. 그리고 Texture Fade Out값에 따라 Main Color의 색상 값이 씌워집니다. 정작 알파값이 적용되면 관절의 겹치는 부분이 보이는 불편한 진실이...

SkeletonGraphic(Premultiply Alpha) : 스탠실 지정 기능이 있습니다. 마스킹도 가능합니다. 예제중에 SkeletonGraphic부분에서 활용 되어있습니다. 캐릭터에서 쓸 일은 잘 모르겠지만, 어딘가 쓰이겠지요.


 그림자 생성의 경우,카메라에 비춰질 그림자 형태를 잡아다가 스프라이트에다가 그려주는 방식입니다. (3D 표면에 그리는 방식이 아닙니다!?)  2D 스프라이트랑 함께 그림자가 한 면에 붙어서 움직이는걸 볼 수 있습니다.  



* 애니메이션 컨트롤 샘플 코드 *


    [SpineEvent] public string footstepEventName = "footstep"; 


    void Start () {

        var skeletonAnimation = GetComponent<SkeletonAnimation>();

        if (skeletonAnimation == null) return;    // told you to add this to SkeletonAnimation's GameObject.


        // This is how you subscribe via a declared method. The method needs the correct signature.

        skeletonAnimation.state.Event += HandleEvent;


        skeletonAnimation.state.Start += delegate (Spine.AnimationState state, int trackIndex) {

            // You can also use an anonymous delegate.

            Debug.Log(string.Format("track {0} started a new animation.", trackIndex));

        };


        skeletonAnimation.state.End += delegate {

            // ... or choose to ignore its parameters.

            Debug.Log("An animation ended!");

        };

    }


    void HandleEvent (Spine.AnimationState state, int trackIndex, Spine.Event e) {

        // Play some sound if the event named "footstep" fired.

        if (e.Data.Name == footstepEventName) {            

            Debug.Log("Play a footstep sound!");

        }

    }

}


Posted by windship
프로그래밍/Spine2017. 1. 29. 18:27

(출처 : http://blog.naver.com/ateliersera/220663774610)



* 초기 셋팅법 *


#region Inspector

[SpineAnimation]

public string runAnimationName;  //스파인은 String으로 동작을 찾게 되어있습니다. 스파인 프리펩에서 동작을 연결해 줍니다.

.

.

public AudioSource footstepAudioSource; //오디오 소스

#endregion


위와같이 사용할 애니메이션을 참조합니다. 이동이나 점프,공격..피격 등 필요한 만큼 작성해 줍니다. 


spineAnimationState.SetAnimation(0, runAnimationName, true);


등으로 사용이 가능합니다. spineAnimationState는 SkeletonAnimation 의 state 에 있는  정보 입니다. 그리고 skeleton 이라는 정보도 있습니다.

skeleton정보는 뼈대에 대한 정보로, X축으로 회전을 시키지 않고, skeleton.FlipX = true; 등을 사용하면 반전해서 사용할 수 있습니다. 


로테이션으로 스파인 유닛을 반전 시킬 경우, 쉐이더에 따라 라이트가 안받는 뒷면이 나오는 등의 문제가 발생 할 수 있습니다.


skeletonAnimation.state.SetAnimation(트랙(번호), 애니메이션이름(스트링), 루프(true/false) 로 3가지 속성이 있습니다. 보통 Idle이나, 이동 의 경우 루프가 true겠지만, 공격 등의 한번만 나와야 하는 모션의 경우에는 false 시켜야 합니다.


*스파인의 애니메이션 섞기 *

유닛이 이동 하면서, 눈을 깜빡이고 싶은데, 눈의 깜빡임은 좀 랜덤하게 나오고 싶다면?

유닛의 이동을 담당하는 애니메이션을 만들고, 이동 애니메이션에는 눈 깜빡임 애니메이션에대한 키값을 만들지 않습니다.  

다른 본들의 움직임에는 애니메이션을 만들지 않고, 눈깜빡이는 애니메이션만을 만듭니다.


위처럼 필요한 동작만을 만든 후, 두 트랙을 동시에 skeletonAnimation.state.SetAnimation 을 통해 플레이 할 경우, 자동으로 섞여서 나오게 됩니다.  매우 간단하지만, 애니메이션 제작 시 염두해 두고 만들어야 할 문제 입니다. 키값이 이미 존재한다면 무언가 하나의 애니메이션은 존재가 사라지는 현상이 발생합니다.




* 스파인 캐릭터의 기본 설정하기 * 

외부 키에 따라 액션을 설정하기 이전에, 모델에 대한 셋팅을 만들어 봅시다.

기본형은 예제에 있는 Spineboy입니다. 

.

.

public class SpineboyBeginnerModel: MonoBehaviour {


#region Inspector

[Header("Current State")]

public SpineBeginnerBodyState state;  //캐릭터의 상태를 위해 만들어진 헤더 입니다. 

public bool facingLeft;   // 좌우 반전을 위해 존재 합니다. 

[Range(-1f, 1f)]

public float currentSpeed; 


[Header("Balance")]

public float shootInterval = 0.12f;  //총 발사의 딜레이를 위한 값 입니다. 

#endregion


float lastShootTime;

public event System.Action ShootEvent; 



// 여기 아래부분은 점프, 발사, 이동을 시도하는 루틴 부분 입니다.

#region API

public void TryJump () {

 StartCoroutine(JumpRoutine());  //코루틴으로 점프 루틴을 돌렸습니다.

}


public void TryShoot () {

 float currentTime = Time.time;

      // 일정 시간이 지나야 슈팅 이벤트가 발생합니다.

 if (currentTime - lastShootTime > shootInterval) {

  lastShootTime = currentTime;

  if (ShootEvent != null) ShootEvent(); // Fire the "ShootEvent" event.

 }

}


public void TryMove (float speed) {

 currentSpeed = speed; // show the "speed" in the Inspector.


 if (speed != 0) {

  bool speedIsNegative = (speed < 0f);

  facingLeft = speedIsNegative; 

 }

 //점프중이 아닐때만 이동을 시도합니다. 

 if (state != SpineBeginnerBodyState.Jumping) {

 state = (speed == 0) ? SpineBeginnerBodyState.Idle : SpineBeginnerBodyState.Running;

 }


}

#endregion

//여기까지가 시도 하는 루틴 부분


IEnumerator JumpRoutine () {

 if (state == SpineBeginnerBodyState.Jumping) yield break; // 점프중일때는 점프를 시도하지 않습니다. 


 state = SpineBeginnerBodyState.Jumping;

 yield return new WaitForSeconds(1.2f); 

 state = SpineBeginnerBodyState.Idle;

 }


}


//state 를 나눠 줍니다. 현재는 세가지.  대기 상태와 뛰기, 점프 상태 입니다. 

public enum SpineBeginnerBodyState {

 Idle,

 Running,

 Jumping

}


//여기까지가 스파인 유닛에 붙는 스크립트 입니다. 간단하게 대기/이동/점/슈팅 으로 되어 있습니다. 이동이나 점프중에 슈팅이 가능한 구조 입니다.

-------------------------------------------------------------------------------------------

* 컨트롤 부분의 스크립트 예제 * 

public class SpineboyBeginnerInput : MonoBehaviour {


 #region Inspector

 public string horizontalAxis = "Horizontal";

 public string attackButton = "Fire1";

 public string jumpButton = "Jump";


 public SpineboyBeginnerModel model;



//OnValidate()가 사용되었는데, 값의 유효성을 검사할때 추가로 사용자 지정 프로세스를 수행하는 메소드 입니다. CollectionBase.OnValidate메소드 입니다.

//Start() 라거나 Awake()에 넣지 않고 값의 유효성 검사를 위해 OnValidate()를 사용했습니다.

 void OnValidate () {

  if (model == null)

   model = GetComponent<SpineboyBeginnerModel>();

 }

 #endregion


 void Update () {

  if (model == null) return;


  float currentHorizontal = Input.GetAxisRaw(horizontalAxis);

  model.TryMove(currentHorizontal);


  if (Input.GetButton(attackButton))

   model.TryShoot();


  if (Input.GetButtonDown(jumpButton))

   model.TryJump();

 }

}


//유닛의 컨트롤 부분에 있어서는 키를 받게 되면 해당 오브젝트에게 이동이나 슈팅, 점프를 시도하도록 명령만 보내는 구조 입니다.  흔히 말하는MVC구조

[출처] Spine2D 튜토리얼 03. 스파인을 가지고 C#에서 사용해 보자.|작성자 세라프


Posted by windship
프로그래밍/Spine2017. 1. 29. 18:25

(출처 : http://ateliersera.blog.me/220653281955)


이전까지만 해도 스파인 프리버젼을 사용해 보다가, 이번에 정품 프로 버젼으로 구매 하였습니다.

약 30만원 가량.. 개발자 분께 투.척...  (개발 하신 분께 수고와 감사의 마음을 담아 *--*)


기본 사용법에 대한 툴팁은 이후에 따로 게시하겠습니다. 일단 성격이 급하니, 돌아가나 확인해 봐야겠지요.

여기까지만 알아도 거의 다 안것과 다름 없습니다. 제작이야 어떻게든 하기 때문입니다. 


스파인의 기본 사용법은 본 구조 타입이고, 애니메이션 제작하기에도 매우 쉽습니다.



위 사진은 테스트 용으로 제작해 보고 있는 횡스크롤 액션 게임에 들어가는 캐릭터 입니다.

동작이 많습니다. 피격의 경우, 방향별로 있고,  애니메이션 보간을 위해, 중간 모션들도 제작해 놓았습니다. 

공격 타격은 5연타 타격이며, 각각 타격과 특별한 스매시 공격 모션을 연결하기 위해 제작된 애니메이션들 입니다.


유니티에서 사용할 데이터를 뽑기 위해, 내보내기를 클릭 해서 JSon 을 선택합니다.


확장자가 json 입니다. 어차피 텍스트 데이터 이지만, 파일의 내부 형식이 그렇습니다. 원하는 출력 폴더를 선택하면, 이름은 프로젝트 이름으로 뽑히게 됩니다.

 

설정 버튼을 누르면..여기서 중요한 부분이 있습니다. 아틀라스 확장자 뒤에 꼭!! .txt 를 붙여 주세요

안그러면 유니티에서 못 읽습니다. . . . . 왜 이걸 아직도 안고쳤는지 모르겠지만.. 안고쳤네요;




이렇게 내보내기 버튼을 누르면, atlas.txt 파일과 json파일, PNG파일이 만들어 집니다. PNG의 경우에 256 컬러 압축 하면 더 작아지겠지요?

Json파일의 경우에도 무압축 순수 텍스트여서 저렇게 용량이 큽니다. 실제로 패킹 할땐 매우 작아집니다.




다음은 유니티쪽 셋업 방법 입니다.



스파인 홈페이지에 있느 유 니티 런타임

위의 주소에 해당 유니티 패키지가 있습니다.


또는 깃 허브에서도 구할 수 있습니다.

https://github.com/EsotericSoftware/spine-runtimes



 



필요한 파일은 이렇게 두개 입니다. 스파인 CSharp과 Unity 입니다. 이 두개를 유니티 에셋 어딘가에 잘 넣어둡니다. 


(웬만한 튜토리얼은 Example\Getting Start를 참고하시면 대부분 해결 됩니다. 만.. 그래도 귀찮으신 분들을 위해, 이후에 제작해서 올리도록 하겠습니다.)




이제 스켈렉톤 데이터를 제작해야 합니다.


앞에서 Export한 파일들을 저장한 폴더로 가서 Create -> Spine Skeleton Data 를 클릭해서 제작해 줍니다.



 

위에 처럼 생겨 있습니다.  JSON 파일에 아까 뽑은 JSON파일을 연결해 준 다음에 Attempt Reimport 를 누 릅니다.


그러면 SkeletonData 파일이 하나 생성이 됩니다.  이로서 사용할 준비는 모두 끝났습니다.


 


이제 씬으로 가서, Spine -> SkeletonAnimation 을 생성 합니다. 


 


Skelecton Data Asset에다가 사용할 스켈렉톤 데이터를 연결해 주면 끝입니다. 이제 나머지는 코드에서 제어하기 나름입니다.

애니메이션을 루핑 시키거나, 타임 스케일링을 주거나, 어떠한 애니메이션을 틀어 줄지, 레이어 소팅은 어디로 할지..등등 의 정보들이 있습니다. 


아래의 영상은 가벼운 이동 테스트 애니메이션 입니다.


Posted by windship
프로그래밍/Spine2015. 6. 19. 14:23