런타임 스켈레톤

Spine 런타임은 뼈대, 슬롯, 어태치먼트 등에 액세스할 수 있습니다. 스켈레톤을 다양한 방법으로 환경에 맞게 맞춤 설정하고 대응시킬 수 있습니다.

월드 변환

뼈대는 각 뼈대가 상위 뼈대에 의해 영향을 받으며 루트 뼈대까지 영향을 받는 계층 구조로 배열됩니다. 예를 들어 뼈대가 회전하면 모든 하위 뼈대와 모든 차하위 뼈대도 회전됩니다. 이를 수행하기 위해 각 뼈대는 다음으로 구성된 로컬 변환을 가집니다:

  • xy
  • rotation
  • scaleXscaleY
  • shearXshearY

루트에서 시작하여 상위 뼈대로 먼저 진행하면 로컬 변환은 각 뼈대에 대한 월드 변환을 계산하는 데 사용됩니다. 월드 변환은 다음으로 구성됩니다:

  • a, b, c, 및 d 이것은 뼈대와 모든 상위 뼈대의 결합 회전, 배율 및 전단을 루트로 다시 인코딩하는 2x2 행렬입니다. ac는 X 축, bd는 Y축입니다.
  • worldXworldY 이것은 뼈대의 월드 위치이며 월드 좌표계는 루트 뼈대가 있는 좌표계입니다.

월드 변환은 모든 점을 뼈대의 로컬 좌표에서 월드 좌표로 변환할 수 있습니다. 예를 들어 뼈대에 첨부된 메쉬의 정점은 뼈대의 월드 변환에 의해 변환됩니다. 결과 정점은 뼈대와 모든 상위 뼈대의 영향을 받습니다. 이 메커니즘은 Spine의 뼈대 애니메이션 시스템의 핵심입니다.

월드 변환은 역으로도 할 수 있으며, 모든 점을 월드 좌표에서 뼈대의 로컬 좌표로 변환할 수 있습니다.

updateWorldTransform

뼈대의 월드 변환은 일반적으로 바로 수정되지 않습니다. 대신 로컬 변환은 수정이 되며 월드 변환은 로컬 변환과 상위 뼈대의 월드 변환을 사용하여 계산됩니다. 뼈대의 로컬 변환이 변경될 때마다 뼈대의 updateWorldTransform을 호출하여 뼈대와 모든 하위 뼈대의 월드 변환을 다시 계산해야 합니다. 하지만 올바른 순서로 뼈대를 업데이트해야 하기 때문에 모든 뼈대를 올바른 순서로 업데이트할 뿐만 아니라 모든 제약 조건을 적용하는 스켈레톤 updateWorldTransform을 호출하는 것이 훨씬 더 일반적입니다.

애니메이션을 적용하면 거의 항상 뼈대 로컬 변환을 수정합니다. 스켈레톤을 렌더링하면 뼈대 월드 변환을 사용합니다. 그러므로 렌더링을 하기 전에 애니메이션을 적용한 후 updateWorldTransform을 호출하는 것이 매우 일반적입니다.

state.update(delta);
state.apply(skeleton);
skeleton.updateWorldTransform();
renderSkeleton(skeleton);

절차적 애니메이션

다양한 효과를 위해 뼈대를 프로그래밍 방식으로 액세스하고 조정할 수 있습니다. 예를 들어 뼈대의 로컬 회전을 설정하여 마우스 커서를 향해 조준할 수 있습니다. IK 대상 뼈대를 프로그래밍 방식으로 배치하는 것이 편리할 수도 있으며, IK 제약 조건을 통해 다양한 IK 믹스로 다양한 뼈대를 조정할 수 있습니다.

애니메이션을 적용한 다음 뼈대를 조정하는 것이 일반적입니다.

Bone torso = skeleton.findBone("torso");
...
state.update(delta);
state.apply(skeleton);
torso.rotation = ... // compute rotation for torso
skeleton.updateWorldTransform();
renderSkeleton(skeleton);
}

뼈대를 조정하기 위해 애니메이션 포즈에서 월드 변환이 필요한 경우, 'updateWorldTransform'을 조정 전에 호출한 다음 로컬 변환을 변경한 후에 다시 호출할 수 있습니다.

Bone torso = skeleton.findBone("torso");
...
state.update(delta);
state.apply(skeleton);
skeleton.updateWorldTransform();
torso.rotation = ... // compute rotation for torso
skeleton.updateWorldTransform();
renderSkeleton(skeleton);

설정 포즈

애니메이션은 설정 포즈와 관련하여 적용됩니다. 즉, BoneData를 조정하면 해당 BoneData를 사용하는 모든 스켈레톤의 모든 애니메이션에 영향을 미칩니다. 애니메이션을 적용하면 BoneData를 사용하므로 애니메이션을 적용하기 전에 변경이 되어야 합니다.

Bone torso = skeleton.findBone("torso");
...
torso.data.rotation = ... // compute rotation for torso
state.update(delta);
state.apply(skeleton);
skeleton.updateWorldTransform();
renderSkeleton(skeleton);

뼈대 위치

뼈대의 월드 변환은 입자 또는 다른 효과와 같은 게임 요소를 배치하는 데 사용할 수 있습니다.

Bone rightHand = skeleton.findBone("right hand");
...
state.update(delta);
state.apply(skeleton);
skeleton.updateWorldTransform();
renderSkeleton(skeleton);
renderParticles(rightHand.worldX, rightHand.worldY);

이 예제에서는 애니메이션이 적용되고, 월드 변환이 계산되고, 스켈레톤이 렌더링된 다음 "오른손" 뼈대의 월드 위치가 입자 효과를 적용하는 데 사용됩니다. 예를 들어 뼈대의 방향으로 입자를 쏘는 것과 같이 뼈대의 월드 회전과 스케일도 사용할 수 있습니다. 비슷한 방식으로 뼈대를 사용해서 UI 요소를 배치, 회전 및 스케일링하여 UI에 애니메이션을 적용하는 데 뼈대 월드 변환을 사용할 수 있습니다.

제네릭 렌더링

특정 게임 툴킷의 런타임은 완벽한 솔루션이며 렌더링을 포함한 모든 작업을 수행합니다. 제네릭 런타임은 게임 툴킷에 의존하지 않으며 실제 렌더링을 제외한 모든 작업을 수행합니다. 제네릭 런타임을 사용하는 경우 렌더링에만 신경 써야 합니다.

제네릭 런타임에 렌더링을 수행하기 위해 스켈레톤 클래스는 그려질 순서대로 슬롯 목록인drawOrder 속성을 제공합니다. 렌더링은 각 슬롯에서 어태치먼트를 검색하고 해당 유형을 검사하며 필요한 경우 렌더링하는 것으로 구성됩니다. 렌더링해야 할 어태치먼트 유형은 다음과 같습니다:

  • RegionAttachment 이것은 4개의 정점을 가지며 사각형입니다(항상 직사각형은 아닙니다).
  • MeshAttachment 이것에는 정점과 삼각형이 여러 개 있습니다. 둘 다 스켈레톤 데이터에 의해 제공되며 렌더러는 삼각 측량을 수행할 필요가 없습니다.

렌더링을 위한 의사 코드는 다음과 같습니다:

foreach (Slot slot in skeleton.drawOrder) {
   Attachment attachment = slot.attachment;
   AtlasRegion region;
   if (attachment is RegionAttachment) {
      attachment.computeWorldVertices(slot.bone, vertices);
      triangles = quadTriangles;
      region = attachment.rendererObject;
   } else if (attachment is MeshAttachment) {
      attachment.computeWorldVertices(slot.bone, vertices);
      triangles = attachment.triangles;
      region = attachment.rendererObject;
   }
   if (texture != null) {
      Texture texture = region.page.rendererObject;
      draw(texture, vertices, triangles, slot.data.blendMode);
   }
}

어태치먼트의 rendererObject 속성은 스켈레톤 데이터가 로드될 때 AttachmentLoader에 의해 설정됩니다. 이 의사 코드에 Spine 아틀라스가 사용된다고 가정하며, rendererObject가 AtlasRegion인 이유입니다.

AtlasRegion에는 아틀라스가 로드될 때 TextureLoader에 의해 설정된 자체 rendererObject 속성이 있는 AtlasPage가 있습니다. 텍스처 클래스는 게임 툴킷 특정 클래스를 나타냅니다.

어태치먼트 변경

지정된 시간에 슬롯에는 하나의 어태치먼트가 있거나 어태치먼트가 없을 수 있습니다. 슬롯에 대한 어태치먼트는 Slot setAttachment을 호출하여 변경할 수 있습니다. 스켈레톤에는 또한 setAttachment 편리한 메서드가 있습니다. 이 메서드는 이름으로 슬롯과 어태치먼트 개체를 찾습니다. 슬롯의 어태치먼트는 다시 변경될 때까지 유지됩니다.

Skeleton skeleton = ...

// Find the slot by name.
Slot slot = skeleton.findSlot("slotName");
// Get the attachment by name from the skeleton's skin or default skin.
Attachment attachment = skeleton.getAttachment(slot.index, "attachmentName");
// Sets the slot's attachment.
slot.attachment = attachment;

// Alternatively, the skeleton setAttachment method does the above.
skeleton.setAttachment("slotName", "attachmentName");

어태치먼트는 다른 방법으로 변경할 수 있습니다. 스켈레톤 setToSetupPose 또는 setSlotsToSetupPose를 호출하면 슬롯 어태치먼트가 변경됩니다. 애니메이션에는 어태치먼트를 변경하는 키 프레임이 있을 수 있습니다. 스켈레톤 setSkin을 호출하면 어태치먼트를 변경할 수 있습니다(스킨 변경 참조).

다음: 런타임 스킨 이전: 애니메이션 적용