ライセンスについて

Spineランタイムをアプリケーションに組み込むにはSpineライセンスが必要です。

spine-unityランタイム ドキュメント

主要なコンポーネント

spine-unityランタイムは、Spineからエクスポートされたスケルトンの表示、アニメーション、追従および修正を可能にするコンポーネントのセットを提供します。これらのコンポーネントは、アセットセクションで説明されているインポートされたスケルトンデータとテクスチャアトラスアセットを参照します。

スケルトンをシーンに追加する

ご自身のUnityプロジェクトにSpineスケルトンを素早く表示するには :

  1. アセットセクションで説明されているスケルトンデータとテクスチャアトラスをインポートします。
  2. _SkeletonDataアセットをSceneビューまたはHierarchyパネルにドラッグし、SkeletonAnimation を選択します。すると、あらかじめ必要なSpineコンポーネントが設定された新しいGameObjectがインスタンス化されます。

補足: STEP2の代わりに、同じGameObjectをいちから作ることもできます :

  1. GameObject -> Create Empty で空のGameObjectを新規作成します。
  2. GameObjectを選択し、Inspectorで Add Component をクリックして、SkeletonAnimation を選択します。これを行うと、追加の MeshRendererMeshFilter コンポーネントも自動的に追加されます。
  3. SkeletonAnimationコンポーネントへ、必要な Skeleton Data Asset をドラッグして、_SkeletonDataプロパティに割り当てます。

注意: Sceneビューで、画像がアタッチされていないボーンだけのスケルトンが表示されてしまう場合、Initial Skin プロパティを default 以外のスキンに切り替えると良いでしょう。

これで、コンポーネントのC# APIを使って、スケルトンをアニメーションさせたり、アニメーション中で発生するイベントへの反応などができるようになります。詳細は後述のコンポーネントのドキュメントを参照してください。

SkeletonAnimationの代わりとなるもの - SkeletonGraphic (UI) と SkeletonMecanim

UnityでSpineスケルトンを使用する上で推奨される方法はSkeletonAnimationとしてスケルトンをインスタンス化することで、3つの選択肢の中で最も完全な機能セットを提供します。

スケルトンをインスタンス化するには、3つの選択肢があります:

  1. SkeletonAnimation - Spineのカスタムアニメーションとイベントシステムを使用し、最高のカスタマイズ性を実現しています。レンダリングには MeshRenderer を使用し、Unityのスプライトと同様にSpriteMask などのマスクと連動します。 これがUnityでSpineのスケルトンを使用する際に推奨されている方法です。
  2. SkeletonGraphic (UI) - Unity Canvasと共にUI要素として使用します。RectMask2DのようなUIマスクを、Unityに元から入っているUI要素のようにレンダリングおよび作用させることができます。アニメーションとイベントの動作はSkeletonAnimationと同じです。
  3. SkeletonMecanim - UnityのMecanimアニメーションとイベントシステムを使用して、アニメーションの開始、ミキシング、アニメーション間の移行(トランジション)を行います。SkeletonAnimationに比べて、アニメーションのミキシングやトランジションの選択肢が少ないという欠点があります。また、SkeletonMecanimを使用した場合、トランジションがSpineエディターでプレビューされた通りに表示されるかは保証されません。

高度な情報 - 実行中でのインスタンス化

注意: 通常のワークフローでは、シーンにスケルトンを追加してプレハブに格納するか、インスタンスプールからプールされたオブジェクトを再利用してインスタンス化するのが望ましいです。その方がカスタマイズや調整が容易になります。

推奨されるワークフローではありませんが、spine-unity APIでは、SkeletonDataAssetから、またはエクスポートされた3つのアセットから直接、実行中に SkeletonAnimationSkeletonGraphic をインスタンス化することができます。エクスポートされたアセットから直接インスタンスを作成するのは、通常のUnityインポートパイプラインでは SkeletonDataAssetSpineAtlasAsset を事前に自動作成できない場合にのみ行うことを推奨します。

C#
// SkeletonAnimation GameObject を SkeletonDataAsset からインスタンス化する
SkeletonAnimation instance = SkeletonAnimation.NewSkeletonAnimationGameObject(skeletonDataAsset);

// SkeletonGraphic GameObject を SkeletonDataAsset からインスタンス化する
SkeletonGraphic instance
   = SkeletonGraphic.NewSkeletonGraphicGameObject(skeletonDataAsset, transform, skeletonGraphicMaterial);
C#
// エクスポートしたアセットを事前にインポートせずにインスタンス化する
// 1. AtlasAssetを作成します (atlas.textアセットとテクスチャ、マテリアル/シェーダーが必要です);
// 2. SkeletonDataAssetを作成します (JSONまたはバイナリアセットファイル、およびAtlasAssetが必要です)
SpineAtlasAsset runtimeAtlasAsset
   = SpineAtlasAsset.CreateRuntimeInstance(atlasTxt, textures, materialPropertySource, true);
SkeletonDataAsset runtimeSkeletonDataAsset
   = SkeletonDataAsset.CreateRuntimeInstance(skeletonJson, runtimeAtlasAsset, true);
// 3. SkeletonAnimationを作成します(有効なSkeletonDataAssetが必要です)
SkeletonAnimation instance = SkeletonAnimation.NewSkeletonAnimationGameObject(runtimeSkeletonDataAsset);

サンプルシーン Spine Examples/Other Examples/Instantiate from Script や、そこで使用されているサンプルスクリプト SpawnFromSkeletonDataExample.csRuntimeLoadFromExportsExample.csSpawnSkeletonGraphicExample.cs でさらに詳しく確認できます。

SkeletonAnimationコンポーネント

SkeletonAnimationコンポーネントは、SpineスケルトンをUnityで使用する3つの方法のうちの1つです。3つの方法とは、SkeletonAnimationSkeletonMecanimSkeletonGraphic (UI)のことです。

SkeletonAnimationコンポーネントは、spine-unityランタイムの核となるものです。SpineスケルトンをGameObjectに追加し、そのスケルトンをアニメーションさせたり、アニメーションイベントに反応させたりすることができます。

Skeleton Data設定

SkeletonAnimationコンポーネントは、スケルトンのボーン階層やスロットなどの情報を取得できるスケルトンデータアセットへの参照を必要とします。

スケルトンをドラッグ&ドロップでSceneに追加した場合、そのスケルトンデータアセットが自動的に割り当てられます。 既に設定されているGameObjectがあってそのスケルトンを別のアセットに変更したくなった場合は、Inspectorプロパティを使って手動で変更することができます。

スケルトンデータを設定・変更するには

  1. SkeletonAnimation GameObjectを選択します。
  2. InspectorのSkeletonData Assetプロパティに _SkeletonData アセットを割り当てます。

初期スキンとアニメーションの設定

SkeletonAnimationのInspectorは以下のパラメーターを公開しています :

  1. Initial Skin : ここで設定したスキンがスタート時に割り当てられます。 注意: 画像がアタッチされていないボーンだけのスケルトンが表示されている場合は、default以外のスキンに切り替えて、スキンを表示した方が良いでしょう。
  2. Animation Name : ここで設定したアニメーションがスタート時に再生されます。
  3. Loop : 初期アニメーションをループさせるか、一度だけ再生するかを定義します。
  4. Time Scale : ここでタイムスケールを設定することで、アニメーションの再生を遅くしたり、速くしたりすることができます。
  5. Unscaled Time : trueに設定すると、アップデートが Time.deltaTime の代わりに Time.unscaledDeltaTime に従って実行されます。これはスローモーションなどの影響を受けずに独立したUI要素をアニメーションさせたい場合などに便利です。

ルートモーションの有効化

SkeletonAnimation およびSkeletonGraphic (UI)コンポーネントのルートモーションは、別のSkeletonRootMotionコンポーネントを介して提供されます。SkeletonAnimation のInspectorには Root Motion Add Component ボタンがあり、適切なコンポーネントをスケルトンのGameObjectに素早く追加できます。

高度なパラメーターの設定

SkeletonAnimationのInspectorのAdvancedセクションを展開すると、高度な設定パラメーターが表示されます。

SkeletonAnimationのInspectorでは、以下の詳細なパラメーターを公開しています

  • Initial Flip X、Initial Flip Y : これらのパラメーターは、スタート時にスケルトンを水平または垂直方向に反転させることができます。これにより、反転した部分のScaleXScaleY-1になります。
  • Animation Update : 通常の Update (デフォルト)、物理ステップ FixedUpdate、またはユーザーコールによる手動アニメーション更新のいずれかを指定します。Rigidbody または Rigidbody2D が割り当てられたSkeletonRootMotionコンポーネントを使用する場合、更新モードを In FixedUpdate に設定することをお勧めします。それ以外の場合は、In Update を推奨します。
  • Update When Invisible : MeshRendererが非表示になったときに使用されるアップデートモードを設定します。メッシュが再び表示されるようになると、アップデートモードは自動的に UpdateMode.FullUpdate にリセットされます。
  • Use single submesh : 1つのマテリアルのみを使用し、1つのサブメッシュのみを必要とすると前提した場合に、サブメッシュの生成を簡素化するために有効にすることができます。これは、複数マテリアルの使用、レンダリングの分割、カスタムスロットマテリアルを無効にします。
  • Fix Draw Order : この設定は3つ以上のサブメッシュが使用されている場合のみ適用されます(2つ以上のマテリアルが交互に並んでいる場合、例:「A B A」)。trueの場合、MaterialPropertyBlockが各マテリアルに割り当てられ、LWRPレンダラーなどによるサブメッシュの積極的なバッチ処理を防ぎ、誤った描画順序になるのを防ぎます(例:「A1 B A2」が「A1 A2 B」に変更される等)。すべてが正しく描画されている場合は、このパラメーターを無効にしておくことでパフォーマンスコストを節約することができます。
  • Immutable triangles : この設定は、アタッチメントの表示状態を変更することが無いスケルトンのレンダリングを最適化するために有効にすることができます。trueの場合、三角形が更新されなくなります。スケルトンがアタッチメントの切り替えや非表示、または描画順序キーを使用しない場合、最適化のためにこれを有効にします。そうでない場合は、これをfalseに設定するとレンダリングでエラーが発生する可能性があります。
  • Clear State on Disable : このコンポーネントまたはそのGameObjectが無効になったときに、レンダーとスケルトンの状態をクリアする設定です。これにより、再び有効になったときに以前の状態が保持されるのを防ぐことができます。スケルトンをプールする場合は、これをtrueに設定すると便利です。
  • Fix Prefab Override MeshFilter : Prefabが常に変更されたものとしてマークされるのを修正します(MeshFilter の非表示フラグを DontSaveInEditor に設定)。 ただし、他のコンポーネントからの MeshFilter への参照は失われます。Use Global Settings に設定すると、Spine Preferencesの設定が使用されます。
  • Separator Slot Names : レンダリングを分割する場所を決めるスロットを設定します。これは SkeletonRenderSeparator などのコンポーネントで使用され、スケルトンを異なるGameObject上に2つの別々のレンダラーでレンダリングすることができます。
  • Z-Spacing : この設定を変更すると、アタッチメントが SkeletonRenderer コンポーネントによって、x/y平面上で前後にレンダリングされるようになります。各アタッチメントが、z軸上のカスタマイズ可能なz-spacing値によってオフセットされ、Zファイティング(z-fighting)を回避します。

  • PMA Vertex Colors : 頂点カラーRGBと頂点カラーアルファを乗算します。レンダリングに使用されているシェーダーがSpineシェーダー(ストレートアルファテクスチャを使用している場合も)またはPMAのAdditive(加算)ブレンドモード Blend One OneMinusSrcAlpha を使用するサードパーティ製シェーダーの場合、このパラメーターを有効にしてください。通常のブレンドモード Blend SrcAlpha OneMinusSrcAlpha を伴う通常のシェーダーの場合は、このパラメーターを無効にしてください。有効にすると、加算スロットを通常スロットと一緒に1回のドローコールでレンダリングできます。無効にすると、加算スロットのために SkeletonDataBlend Mode Materials - Apply Additive Material を有効にする必要があり、このために別のドローコールが必要になってしまうので、パフォーマンスに悪影響を与える可能性があります。
  • Tint Black (!) : ブラックティントの頂点データをメッシュに追加します。スケルトンの中にティントブラックが設定されたスロットがあれば有効にしてください。 ブラックティントは、この効果が機能するために、シェーダーがUV2とUV3をブラックティントカラーとして解釈する必要があります。そのために付属の Spine/Skeleton Tint Black シェーダーを使用することができます。個々のパーツではなくスケルトン全体を着色する必要がある場合は、効率が良く、MaterialPropertyBlockで _Black マテリアルプロパティを変更およびアニメーションさせることができる Spine/Skeleton Tint シェーダーをお勧めします。詳しくはシェーダーセクションを参照してください。複数のスケルトンを異なる方法でティントする際にバッチングを維持するにはSkeleton.R .G .B .Aによるティントをお勧めします。
  • Add Normals : 有効にすると、メッシュジェネレーターは出力メッシュに法線を追加します。使用するシェーダーが頂点法線を必要とする場合に有効にしてください。パフォーマンスを向上させ、メモリ使用量を削減するには、代わりに Spine/Skeleton Lit シェーダーのような、希望する法線を想定するシェーダーを使用することができます。Spine/Sprite シェーダーは Fixed Normal を仮定するようにも設定できることに注意してください。
  • Solve Tangents : 一部のライトシェーダーは、通常、ノーマルマップ(法線マップ)を適用するために、頂点接線を必要とします。有効にすると、毎フレームで接線が計算され、出力メッシュに追加されます。
  • Physics Inheritance : トランスフォームの動きをスケルトンの物理コンストレイントに適用する方法を制御します。
    • Position : ゼロ以外に設定すると、X方向およびY方向のトランスフォームの位置移動がスケルトンの物理コンストレイントに適用され、ここで設定したXおよびYのスケール係数で乗算されます。一般的な組み合わせは以下の通りです:
      (1,1) にした場合、XY移動が通常通り適用されます。
      (2,2) にした場合、XY移動が倍の強さで適用されます。
      (1,0) にした場合、水平方向の移動だけが適用されます。
      (0,0) にした場合、トランスフォームの移動の動きは全く適用されなくなります。
    • Rotation : ゼロ以外に設定すると、トランスフォームの回転の動きがスケルトンの物理コンストレイントに適用され、ここで設定したスケール係数で乗算されます。一般的な値は以下の通りです:
      1 にした場合、通常通り適用されます。
      2 にした場合、倍の強さで適用されます。
      0 にした場合、トランスフォームの回転の動きは全く適用されなくなります。
    • Movement relative to 親トランスフォームなどに対する相対的なトランスフォームの動きを適用するには、これを動きを計算する基準となるトランスフォームに設定します。None に設定すると、ワールドの絶対位置(デフォルト)を使用します。
  • Add Skeleton Utility : このボタンを使用すると、ボーンの位置をトラッキングしたり、オーバーライドしたりするための SkeletonUtility コンポーネントをGameObjectに素早く追加することができます。詳しくはSkeletonUtilityを参照してください。
  • Debug : ゲームの実行中にスロットの現在のカラーやボーンのスケール値などの情報を知りたい時は、Debugボタンを押せばデバッグ用のSkeleton Debugウィンドウを開けます。ここで、ボーン、スロット、コンストレイント、表示順序、イベント、スケルトンの統計情報などの現在の状態を確認することができます。

ライフサイクル


SkeletonAnimationコンポーネントでは、AnimationStateが現在再生中のアニメーションやキューされたアニメーションのステート(状態)を保持しています。 Update ごとにAnimationStateが更新され、アニメーションが時間的に進むようになります。そして、新しいフレームが新しいポーズとしてスケルトンに適用されます。

スクリプトは、SkeletonAnimationの Update の前でも後でも実行できます。 あなたのコードがSkeletonAnimationのUpdateの前にスケルトンまたはボーンの値を取得する場合、コードは現在のフレームではなく前のフレームから値を読み取ります。

このコンポーネントは、イベントコールバックデリゲートをプロパティとして公開しており、すべてのボーンのワールドトランスフォームが計算される前と後に、このライフサイクルをインターセプトすることができます。これらのデリゲートにバインドすることで、アクターやコンポーネントの更新順序を気にすることなく、ボーンの位置やスケルトンの他の側面を修正することができます。

SkeletonAnimation Update コールバック

  • SkeletonAnimation.BeforeApply は、そのフレームのアニメーションが適用される前に発生します。このコールバックは、アニメーションが適用される前にスケルトンの状態を変更したい場合に使用します。
  • SkeletonAnimation.UpdateLocal は、そのフレームのアニメーションが更新され、スケルトンのローカル値に適用された後に発生します。ボーンのローカル値を読み込んだり修正したりする必要がある場合に使用します。
  • SkeletonAnimation.UpdateComplete は、Skeletonのすべてのボーンに対してワールド値が計算された後に発生します。SkeletonAnimationは、この後、Updateでそれ以上の操作をしません。ボーンのワールド値を読み取る必要がある場合は、これを使用してください。これらの値は、SkeletonAnimationのUpdate後にスクリプトが変更すると、まだ変更される可能性があります。
  • SkeletonAnimation.UpdateWorld は、Skeletonのすべてのボーンについてワールド値が計算された後に発生します。このイベントをサブスクライブすると、skeleton.UpdateWorldTransform が2回目に呼び出されます。スケルトンの複雑さやあなたがやっていることによっては、これは不要であったり、無駄であったりします。このイベントは、ボーンのワールド値に基づいて、ボーンのローカル値を修正する必要がある場合に使用します。これは、Unityのコードでカスタムコンストレイントを実装するのに便利です。

C#
// ここにあなたのデリゲートメソッド
void AfterUpdateComplete (ISkeletonAnimation anim) {
   // これはアニメーションの更新が完了した後に呼び出されます
}

// あなたのデリゲートメソッドを登録
void Start() {
   skeletonAnimation.UpdateComplete -= AfterUpdateComplete;
   skeletonAnimation.UpdateComplete += AfterUpdateComplete;
}

SkeletonRenderer Update コールバック

  • OnRebuild は、スケルトンが正常に初期化された後に発生します。
  • OnMeshAndMaterialsUpdated は、メッシュとすべてのマテリアルが更新された後、LateUpdate() の最後に発生します。

C#
// OnMeshAndMaterialsUpdated 用のデリゲートメソッド
void AfterMeshAndMaterialsUpdated (SkeletonRenderer renderer) {
   // これはメッシュとマテリアルが更新された後に呼び出されます
}

// OnRebuild 用のデリゲートメソッド
void AfterRebuild (SkeletonRenderer renderer) {
   // これはスケルトンが正常に初期化された後に呼び出されます
}

// あなたのデリゲートメソッドを登録
void Start() {
   skeletonAnimation.OnMeshAndMaterialsUpdated -= AfterMeshAndMaterialsUpdated;
   skeletonAnimation.OnMeshAndMaterialsUpdated += AfterMeshAndMaterialsUpdated;

   skeletonAnimation.OnRebuild -= AfterRebuild;
   skeletonAnimation.OnRebuild += AfterRebuild;
}

別の方法として、スクリプトの実行順序をSkeletonAnimationのUpdateメソッドの後に実行するように変更することもできます。

UnityのMonoBehaviourのライフサイクルについては、こちらをご覧ください: docs.unity3d.com/Manual/ExecutionOrder

C#

スケルトンをコードで操作するには、SkeletonAnimationコンポーネントにアクセスする必要があります。一般的なUnityコンポーネントと同様に、一度リファレンスを参照して、その後の使用のために保存しておくことをお勧めします。

C#
...
using Spine.Unity;

public class YourComponent : MonoBehaviour {

   SkeletonAnimation skeletonAnimation;
   Spine.AnimationState animationState;
   Spine.Skeleton skeleton;

   void Awake () {
      skeletonAnimation = GetComponent<SkeletonAnimation>();
      skeleton = skeletonAnimation.Skeleton;
      //skeletonAnimation.Initialize(false); // skeletonAnimation.Skeletonにアクセスしない場合
                                 // Initialize(false)を使用して、すべてがロードされていることを確認します。
      animationState = skeletonAnimation.AnimationState;
   }

Skeleton

SkeletonAnimationコンポーネントは、SkeletonAnimation.Skeletonプロパティを介して、基礎となるSkeletonへのアクセスを提供します。Skeletonには、スケルトンデータアセットへの参照が格納されており、このアセットは1つまたは複数のアトラスアセットを参照します。

Skeletonでは、スキンやアタッチメントを設定したり、ボーンをリセットしてポーズやスケールを設定したり、スケルトン全体を反転させたりすることができます。

アタッチメントの設定

アタッチメントを設定するには、スロットとアタッチメント名を入力します。

C#
bool success = skeletonAnimation.Skeleton.SetAttachment("slotName", "attachmentName");
C#
// プロパティを使用する場合
[SpineSlot] public string slotProperty = "slotName";
[SpineAttachment] public string attachmentProperty = "attachmentName";
...
bool success = skeletonAnimation.Skeleton.SetAttachment(slotProperty, attachmentProperty);

上記コード中の[SpineSlot][SpineAttachment]は、こちらのセクションで説明しているStringのプロパティ属性(Attribute)です。

セットアップポーズへのリセット

プロシージャルなアニメーションでは、ボーンやスロットをセットアップのポーズに戻すことが必要な場合があります。スキンを設定した後は、後述のスキンの設定セクションで説明するように Skeleton.SetSlotsToSetupPose を呼び出す必要があるケースが多いでしょう。

C#
skeleton.SetToSetupPose();
skeleton.SetBonesToSetupPose();
skeleton.SetSlotsToSetupPose();

スキンの設定

Spineスケルトンは、どのアタッチメントをどのスロットに装着するかを定義する複数のスキンを持っている場合があります。Skeletonコンポーネントは、スキンを切り替える簡単な方法を提供します。

C#
bool success = skeletonAnimation.Skeleton.SetSkin("skinName");
skeletonAnimation.Skeleton.SetSlotsToSetupPose(); // 後述の補足を参照
C#
// プロパティを使用する場合
[SpineSkin] public string skinProperty = "skinName";
...
bool success = skeletonAnimation.Skeleton.SetSkin(skinProperty);
skeletonAnimation.Skeleton.SetSlotsToSetupPose(); // 後述の補足を参照

以前に設定したアタッチメントが現在のアタッチメントの表示に影響するのを避けたい場合、スキンを変更した後に Skeleton.SetSlotsToSetupPose を呼び出す必要があります。詳細はこちらのドキュメントを参照してください。

スキンの組み合わせ

Spineスキンは組み合わせることが可能です。例えば、衣装アイテムスキンを組み合わせて完全なキャラクタースキンを形成することができます。 詳細は、新しいSkin APIドキュメントをご覧ください。

C#
var skeleton = skeletonAnimation.Skeleton;
var skeletonData = skeleton.Data;
var mixAndMatchSkin = new Skin("custom-girl");
mixAndMatchSkin.AddSkin(skeletonData.FindSkin("skin-base"));
mixAndMatchSkin.AddSkin(skeletonData.FindSkin("nose/short"));
mixAndMatchSkin.AddSkin(skeletonData.FindSkin("eyelids/girly"));
mixAndMatchSkin.AddSkin(skeletonData.FindSkin("eyes/violet"));
mixAndMatchSkin.AddSkin(skeletonData.FindSkin("hair/brown"));
mixAndMatchSkin.AddSkin(skeletonData.FindSkin("clothes/hoodie-orange"));
mixAndMatchSkin.AddSkin(skeletonData.FindSkin("legs/pants-jeans"));
mixAndMatchSkin.AddSkin(skeletonData.FindSkin("accessories/bag"));
mixAndMatchSkin.AddSkin(skeletonData.FindSkin("accessories/hat-red-yellow"));
skeleton.SetSkin(mixAndMatchSkin);
skeleton.SetSlotsToSetupPose();
skeletonAnimation.AnimationState.Apply(skeletonAnimation.Skeleton); // SkeletonMecanimの場合は skeletonMecanim.Update() を使用してください

ランタイムでの再パッキング

スキンを組み合わせると、複数のマテリアルが蓄積されることがあります。しかしこれは、ドローコールの増加につながってしまいます。 Skin.GetRepackedSkin()メソッドを使えば、収集したスキンに使用されているテクスチャ領域を、実行時に単一のテクスチャにまとめることができます。

C#
using Spine.Unity.AttachmentTools;

// 再パックされたスキンを作成します。
Skin repackedSkin = collectedSkin.GetRepackedSkin("Repacked skin", skeletonAnimation.SkeletonDataAsset.atlasAssets[0].PrimaryMaterial, out runtimeMaterial, out runtimeAtlas);
collectedSkin.Clear();

// 再パックされたスキンを使用します。
skeletonAnimation.Skeleton.Skin = repackedSkin;
skeletonAnimation.Skeleton.SetSlotsToSetupPose();
skeletonAnimation.AnimationState.Apply(skeletonAnimation.Skeleton); // skeletonMecanim.Update() for SkeletonMecanim

// オプションとして、複数の再パック操作後にキャッシュをクリアすることができます。
AtlasUtilities.ClearCache();

重要な注意事項: 再パッキングに失敗したり、予期せぬ結果になる場合は、以下の原因が考えられます。:

  1. Read/Writeが無効になっている : プラットフォームの性能によっては、再パックされたテクスチャに結合されるソーステクスチャに Read/Write Enabled パラメーターを設定する必要があります。
  2. Compressionが有効になっている : プラットフォームによっては、ソーステクスチャのテクスチャインポート設定の CompressionNormal Quality ではなくNone に設定されていることを確認してください。
  3. Qualityの設定で、半分または1/4の解像度のテクスチャを使用している : 半分または1/4の解像度のテクスチャが使用されている場合、正しくない領域がコピーされるというUnityの既知のバグがあります。Project SettingsのQualityの設定がすべてフル解像度のテクスチャを使用していることを確認してください。
  4. ソーステクスチャが2のべき乗になっていなくてもUnityがそれを最も近い累乗に拡大している : このため、a)パック設定Power of two(2のべき乗) を有効にしてSpineからエクスポートするか、b)Unityのアトラステクスチャのインポート設定で Non-Power of TwoNone になっていることを確認してください。

さらに深く理解するには、サンプルシーンの Spine Examples/Other Examples/Mix and MatchSpine Examples/Other Examples/Mix and Match Equip、そして使用されている MixAndMatch.cs のサンプルスクリプトを参考にしてください。

高度な情報 - ノーマルマップと一緒にランタイムで再パッキングする

メインテクスチャと一緒に、ノーマルマップ(法線マップ)やその他の追加テクスチャレイヤーを再パックすることもできます。 int[] additionalTexturePropertyIDsToCopy = new int[] { Shader.PropertyToID("_BumpMap") };GetRepackedSkin() のパラメーターとして渡すことで、メインテクスチャとノーマルマップ(法線マップ)レイヤーの両方を再パックすることができます。

C#
Material runtimeMaterial;
Texture2D runtimeAtlas;
Texture2D[] additionalOutputTextures = null;
int[] additionalTexturePropertyIDsToCopy = new int[] { Shader.PropertyToID("_BumpMap") };
Skin repackedSkin = prevSkin.GetRepackedSkin("Repacked skin", skeletonAnimation.SkeletonDataAsset.atlasAssets[0].PrimaryMaterial, out runtimeMaterial, out runtimeAtlas,
additionalTexturePropertyIDsToCopy : additionalTexturePropertyIDsToCopy, additionalOutputTextures : additionalOutputTextures);

// 再パックされたスキンを使用します。
skeletonAnimation.Skeleton.Skin = repackedSkin;
skeletonAnimation.Skeleton.SetSlotsToSetupPose();
skeletonAnimation.AnimationState.Apply(skeletonAnimation.Skeleton); //SkeletonMecanimの場合はskeletonMecanim.Update()

注意: 通常、ノーマルマップ(法線マップ)のプロパティは"_BumpMap"という名前になっていますが、カスタムシェーダーを使用する場合は、必ずそれぞれのプロパティ名を使用してください。なお、この名前はシェーダー内のプロパティ名であり、Inspectorに表示される"Normal Map"ラベル文字列ではないことに注意してください。

スケルトンのスケール変更と反転

スケルトンを垂直または水平方向に反転させることで、アニメーションを再利用することができます。例えば、左向きの歩行アニメーションを右向きにして再生することができます。

C#
bool isFlippedX = skeleton.ScaleX < 0;
skeleton.ScaleX = -1;
bool isFlippedY = skeleton.ScaleY < 0;
skeleton.ScaleY = -1;

skeleton.ScaleX = -skeleton.ScaleX; // x反転の状態を切り替え

ボーントランスフォームへの手動アクセス

注意: こちらは非常に特殊なケースでのみ使用することをお勧めします。 SpineのBoneFollowerSkeletonUtilityBoneコンポーネントの方がより簡単にボーンを操作することができます。

Skeletonでは、ボーンのトランスフォーム値を設定・取得できるので、IKによる地形追従を実装したり、パーティクルシステムなどの他のアクターやコンポーネントをスケルトンのボーンに追従させることができます。

注意: SkeletonAnimation.UpdateWorldデリゲートをサブスクライブすることで、ワールドトランスフォームの更新のライフサイクルの一部として新しいボーンの位置を取得して適用するようにしてください。そうしないと、ロード時に修正が1フレーム遅れたり、設定したときにアニメーションによって上書きされたりする可能性があります。

C#
Bone bone = skeletonAnimation.Skeleton.FindBone("boneName");
Vector3 worldPosition = bone.GetWorldPosition(skeletonAnimation.transform);
// 注意:SkeletonGraphicを使用する場合、すべての値は親のCanvas.referencePixelsPerUnitでスケーリングする必要があります。

Vector3 position = ...;
bone.SetPositionSkeletonSpace(position);

Quaternion worldRotationQuaternion = bone.GetQuaternion();

アニメーション - AnimationState

ライフサイクル

SkeletonAnimationコンポーネントは Update メソッドを実装しています。このメソッドでは、デルタタイムに基づいて基礎となるAnimationStateを更新し、そのAnimationStateをスケルトンに適用し、スケルトンのすべてのボーンのワールドトランスフォームを更新します。

SkeletonAnimationコンポーネントは、SkeletonAnimation.AnimationState プロパティを介してAnimationStateAPIを公開しています。このセクションでは、トラック、TrackEntry、ミックスタイム、アニメーションのキューイングなどの概念について、全般的なSpineランタイムガイドのアニメーションの適用の項で説明されている内容を前提としています。

タイムスケール

SkeletonAnimationコンポーネントのタイムスケールを設定することで、アニメーションの再生を遅くしたり、速くしたりすることができます。例えば、タイムスケールが0.5の場合、アニメーションは通常の半分の速度になり、タイムスケールが2の場合、アニメーションは通常の2倍の速度になるというように、アニメーションの進行に使用されるデルタタイムは、単純にタイムスケールを乗じたものになります。

C#
float timeScale = skeletonAnimation.timeScale;
skeletonAnimation.timeScale = 0.5f;

アニメーションの設定

アニメーションを設定するには、トラックのインデックス、アニメーション名、アニメーションをループさせるかどうかを指定します。

C#
TrackEntry entry = skeletonAnimation.AnimationState.SetAnimation(trackIndex, "walk", true);
C#
// プロパティを使用する場合
[SpineAnimation] public string animationProperty = "walk";
...
TrackEntry entry = skeletonAnimation.AnimationState.SetAnimation(trackIndex, animationProperty, true);

別の方法として、文字列ではなくAnimationReferenceAssetをパラメーターとして使用することもできます。

C#
// AnimationReferenceAssetを使用する場合
public AnimationReferenceAsset animationReferenceAsset; // 生成された AnimationReferenceAsset をこのプロパティに割り当てます。
...
TrackEntry entry = skeletonAnimation.AnimationState.SetAnimation(trackIndex, animationReferenceAsset, true);

アニメーションのキューイング

アニメーションをキューに入れるには、トラックのインデックス、アニメーション名、アニメーションをループさせるかどうか、このアニメーションがトラックで再生を開始するまでの遅延時間を秒単位で指定します。

C#
TrackEntry entry = skeletonAnimation.AnimationState.AddAnimation(trackIndex, "run", true, 2);
C#
// プロパティを使用する場合
[SpineAnimation] public string animationProperty = "run";
...
TrackEntry entry = skeletonAnimation.AnimationState.AddAnimation(trackIndex, animationProperty, true, 2);

空のアニメーションとクリア処理

SkeletonAnimationコンポーネントには、空のアニメーションを設定したり、空のアニメーションをキューに入れたり、1つまたはすべてのトラックをクリアするメソッドも用意されています。これらはすべて、上述のメソッドやノードと同様に動作します。

C#
TrackEntry entry = skeletonAnimation.AnimationState.SetEmptyAnimation(trackIndex, mixDuration);
entry = skeletonAnimation.AnimationState.AddEmptyAnimation(trackIndex, mixDuration, delay);
skeletonAnimation.AnimationState.ClearTrack(trackIndex);
skeletonAnimation.AnimationState.ClearTracks();

TrackEntry

すべてのメソッドからTrackEntryを受け取り、特定のアニメーションの再生をさらにカスタマイズしたり、TrackEntryのイベントのデリゲートにバインドしたりすることができます。詳しくは後述の「AnimationStateイベントの処理」をご覧ください。

注意: 返されたTrackEntryは、対応するアニメーションが根底となるAnimationStateから削除されるまでのみ有効です。Unityのガベージコレクターが自動的にこれらを解放します。TrackEntryのdisposeイベントを受け取った後は、もう保存もアクセスもしないようにしてください。

C#
TrackEntry entry = ...
entry.EventThreshold = 2;
float trackEnd = entry.TrackEnd;

AnimationStateイベントの処理

アニメーションがAnimationStateによって再生されている間、様々なイベントが発行され、リスナーに以下を通知します。

  1. アニメーションが開始された(start)
  2. トラックをクリアしたり、新しいアニメーションを設定するなどして、アニメーションが中断された(interrupt)
  3. 途切れることなくアニメーションが完了した(complete)。※ループしている場合は複数回発生
  4. アニメーションが終了した(end)
  5. アニメーションとそれに対応するTrackEntry破棄された(dispose)
  6. ユーザーが定義したイベント(event)が発生した。

補足: 前のアニメーションを中断して新しいアニメーションを設定した場合、completeイベントは発生せず、代わりにinterruptendイベントが発生します。

SkeletonAnimationコンポーネントは、すべてのトラックでキューイングされたすべてのアニメーションのイベントに反応するために、C#コードがバインドできるデリゲートを提供します。また、リスナーは特定のTrackEntryの対応するデリゲートにのみバインドすることもできます。例えばAnimationState.Completeに登録すればあらゆるアニメーションのCompleteイベントで処理が実行され、TrackEntry.Completeに登録すれば特定のアニメーションによって発行されたCompleteイベントのみを処理することができます。

C#

AnimationStateイベントに反応するクラスで、取得したいイベントのデリゲートを追加します:

C#
SkeletonAnimation skeletonAnimation;
Spine.AnimationState animationState;

void Awake () {
   skeletonAnimation = GetComponent<SkeletonAnimation>();
   animationState = skeletonAnimation.AnimationState;

   // あらゆるアニメーションから発生されるイベントに対して登録する
   animationState.Start += OnSpineAnimationStart;
   animationState.Interrupt += OnSpineAnimationInterrupt;
   animationState.End += OnSpineAnimationEnd;
   animationState.Dispose += OnSpineAnimationDispose;
   animationState.Complete += OnSpineAnimationComplete;

   animationState.Event += OnUserDefinedEvent;

   // 特定のアニメーショントラックエントリーから発生されるイベントに対して登録する
   Spine.TrackEntry trackEntry = animationState.SetAnimation(trackIndex, "walk", true);
   trackEntry.Start += OnSpineAnimationStart;
   trackEntry.Interrupt += OnSpineAnimationInterrupt;
   trackEntry.End += OnSpineAnimationEnd;
   trackEntry.Dispose += OnSpineAnimationDispose;
   trackEntry.Complete += OnSpineAnimationComplete;
   trackEntry.Event += OnUserDefinedEvent;
}

public void OnSpineAnimationStart(TrackEntry trackEntry) {
   // startイベントに反応させたい実装コードをここに追加してください
}
public void OnSpineAnimationInterrupt(TrackEntry trackEntry) {
   // interruptイベントに反応させたい実装コードをここに追加してください
}
public void OnSpineAnimationEnd(TrackEntry trackEntry) {
   // endイベントに反応させたい実装コードをここに追加してください
}
public void OnSpineAnimationDispose(TrackEntry trackEntry) {
   // disposeイベントに反応させたい実装コードをここに追加してください
}
public void OnSpineAnimationComplete(TrackEntry trackEntry) {
   // completeイベントに反応させたい実装コードをここに追加してください
}


string targetEventName = "targetEvent";
string targetEventNameInFolder = "eventFolderName/targetEvent";

public void OnUserDefinedEvent(Spine.TrackEntry trackEntry, Spine.Event e) {

   if (e.Data.Name == targetEventName) {
      // ユーザー定義イベントに反応させたい実装コードをここに追加してください
   }
}

// イベントデータをキャッシュすることで、文字列の比較を省略することができます
Spine.EventData targetEventData;
void Start () {
   targetEventData = skeletonAnimation.Skeleton.Data.FindEvent(targetEventName);
}
public void OnUserDefinedEvent(Spine.TrackEntry trackEntry, Spine.Event e) {

   if (e.Data == targetEventData) {
      // ユーザー定義イベントに反応させたい実装コードをここに追加してください
   }
}

詳細はSpine API Referenceをご覧ください。

コールバック内でのAnimationStateやゲームのステートの変更について

AnimationState のイベントコールバックから AnimationState.SetAnimation() を呼び出すなどして AnimationState を変更することができますが、ここには考慮すべき以下のようなタイミングの問題があります。これは、イベントコールバックからゲームステートを変更する場合にも当てはまります。

  1. AnimationState イベントコールバックは SkeletonAnimation.Update() でアニメーションが適用されるときに発行され、SkeletonAnimation.LateUpdate() でメッシュが更新されるよりも前に発行されます。
  2. AnimationState.Endコールバックから AnimationState.SetAnimation() を呼び出すと、同じフレームで AnimationState.Start イベントがトリガーされます。
  3. 1つのアニメーションから別のアニメーションへのミックストランジションのために、Start イベントは1つ目のアニメーションの End イベントよりも 前に 発行されます。これは、ゲームステートを変更するときに考慮すべきよくある落とし穴です。

このようなイベントコールバック内からの呼び出しを、次の Update() サイクルまで遅らせたい場合は、次のように StartCoroutine を使用できます:

C#
trackEntry.End += e => {
   StartCoroutine(NextFrame(() => {
      YourCode();
   }));
};

...

IEnumerator NextFrame (System.Action call) {
   yield return 0;
   if (call != null)
      call();
}

コルーチンのyield命令

spine-unityランタイムは、Unityのコルーチン(Coroutines)で使用するための一連のyield命令を提供しています。Unityのコルーチンを初めて使用される方は、コルーチンのチュートリアルコルーチンのドキュメントから始めることをお勧めします。

以下のようなyield命令があります:

  1. WaitForSpineAnimation Spine.TrackEntry が指定されたイベントの1つを発生させるまで待機します。

    C#
    var track = skeletonAnimation.state.SetAnimation(0, "interruptible", false);
    var completeOrEnd = WaitForSpineAnimation.AnimationEventTypes.Complete |
                          WaitForSpineAnimation.AnimationEventTypes.End;
    yield return new WaitForSpineAnimation(track, completeOrEnd);
  2. WaitForSpineAnimationComplete Spine.TrackEntryComplete イベントを発生させるまで待機します。

    C#
    var track = skeletonAnimation.state.SetAnimation(0, "talk", false);
    yield return new WaitForSpineAnimationComplete(track);
  3. WaitForSpineAnimationEnd Spine.TrackEntryEnd イベントを発生させるまで待機します。

    C#
    var track = skeletonAnimation.state.SetAnimation(0, "talk", false);
    yield return new WaitForSpineAnimationEnd(track);
  4. WaitForSpineEvent Spine.AnimationState が、ユーザーが定義したSpine.Event(Spineエディター内で命名)を発生させるまで待機します。

    C#
    yield return new WaitForSpineEvent(skeletonAnimation.state, "spawn bullet");
    // Spine.EventのSpine.EventDataリファレンスを渡すこともできます。
    Spine.EventData spawnBulletEvent; // Start() などでキャッシュされます。
    ..
    yield return new WaitForSpineEvent(skeletonAnimation.state, spawnBulletEvent);

補足: Unityに組み込まれているyield命令と同様に、spine-unityのyield命令のインスタンスも再利用することができ、追加のメモリ割り当てを防ぐことができます。

チュートリアルページ

こちらでspine-unityのイベントのチュートリアルページを確認できます。

stringのプロパティ属性のスクリプティング

Inspectorでアニメーションの名前などを手入力するのは少し手間がかかります。そこでspine-unityは文字列(string)パラメーターのポップアップフィールドを提供します。stringプロパティの前に以下のプロパティ属性(Attribute)のいずれかを指定すると、スケルトンで利用可能なすべてのアニメーションなどが入力されたポップアップ選択フィールドが自動的に表示されます。提供されているSpineコンポーネントにこのようなポップアップフィールドがある場合、カスタムコンポーネントでもプロパティ属性を使って同じポップアップを使用することができます。以下は利用可能なプロパティ属性の一覧です。

C#
[SpineBone] public string bone;
[SpineSlot] public string slot;
[SpineAttachment] public string attachment;
[SpineSkin] public string skin;
[SpineAnimation] public string animation;
[SpineEvent] public string event;
[SpineIkConstraint] public string ikConstraint;
[SpineTransformConstraint] public string transformConstraint;
[SpinePathConstraint] public string pathConstraint;

spine-unityパッケージに含まれるサンプルシーンで、stringプロパティ属性が使用されているのを確認してみてください。

SkeletonMecanimコンポーネント

SkeletonMecanimコンポーネントは、UnityでSpineスケルトンを使用する3つの方法のうちの1つです。3つの方法とは、SkeletonAnimationSkeletonMecanimSkeletonGraphic (UI)のことです。

SkeletonMecanimコンポーネントはSkeletonAnimationコンポーネントの代わりに使用できるもので、Spineのアニメーションシステムの代わりにUnityのMecanimアニメーションシステムを使用します。SkeletonAnimationコンポーネントと同様に、SpineスケルトンをGameObjectに追加し、アニメーションさせたり、アニメーションイベントに反応させたりすることができます。ただし、SkeletonAnimationと比較して以下のようないくつかの制限と追加要件があります:

注意: SkeletonAnimationコンポーネントと異なりSkeletonMecanimは先行するアニメーションのタイムラインの状態をスムーズにミックスアウトするために、アニメーションの最初のフレームで追加のタイムラインキーを必要とします。詳しくは後述の必要になる追加のキーをご覧ください。

注意: TrackEntry.MixAttachmentThresholdおよび同様のミックスしきい値の機能はSkeletonMecanimでは使用できません。

SkeletonMecanimコンポーネントにはSkeletonAnimationコンポーネントと類似したパラメーターが用意されているので、詳しくはSkeletonAnimationセクションを参照してください。

必要になる追加のキー

あるアニメーションから次のアニメーションへとタイムラインの状態(ボーンの回転など)をスムーズにミックスアウトさせるために、2つ目のアニメーションでは、最初のフレームでセットアップポーズの状態の追加のキーが必要になります。そうしないと、前のアニメーションのタイムラインの状態が残ってしまうからです。これはSkeletonAnimationと比較した際のSkeletonMecanimの欠点の一つです。

簡単な例: idle アニメーションが、先に再生されている jump アニメーションをスムーズにミックスアウトする必要があるとします。jump の終了時にボーン bone1bone2 がセットアップポーズとは異なる位置でキー設定されている場合、jump の状態を適切にミックスアウトするためには、idleアニメーションの最初のフレームに bone1bone2 のキー(セットアップポーズまたは任意のポーズ)を追加する必要があります。

Auto Reset パラメーターを使えばタイムラインの状態をリセットできますが、アニメーションのトランジション終了時に唐突にミックスアウトしてしまい、スムーズなトランジションを実現できません。

また、スケルトンを .json または .skel.bytes でエクスポートする際は必ず Animation cleanup(アニメーションクリーンアップ) を無効にしてください。そうしないとセットアップポーズと全く同じキーはエクスポートされなくなってしまいます!

アニメーションブレンドのコントロール

SkeletonMecanimのInspectorは以下の追加パラメーターを公開しています :

  • Mecanim Translator

    • Auto Reset : true に設定すると、アニメーションが終了したときに、アニメーションのキーが設定されたアイテムに応じて、スケルトンの状態がセットアップポーズにミックスアウトされます。これは、アニメーションがアタッチメントの表示状態を変更した場合に特に重要になることがあります。ミックスアウトされると、アタッチメントの表示状態はセットアップポーズの状態に戻りますが、そうでなければ、現在のアタッチメントの状態は別のアニメーションがそれぞれのアタッチメントのタイムラインにキーを設定するまで保持されます。

    • Custom MixMode : 無効にすると、レイヤーのブレンドモードに応じて、推奨されるMixMode が使用されます。有効にすると、以下のような Mix Modes セクションが表示され、各Mecanimレイヤーの MixMode を指定することができます。

    • Mix Modes : 上記の Custom MixMode パラメーターが有効な場合に表示されます。このパラメーターは、連続したアニメーション間、およびレイヤー間のアニメーションのミックスモードを決定します。

      • Mix Next Base LayerOverride レイヤーで推奨されます)
        前のトラックを適用した後、Mecanimのトランジションウェイトを使って次のトラックを上からミックスします。
      • Always Mix Additive レイヤーで推奨されます)
        前のトラックをフェードアウトし(Auto Reset が有効な場合、セットアップポーズになる可能性があります)、Mecanimのトランジションウェイトを使用して次のトラックをトップにミックスします。Base Layerに使用すると、意図しないアニメーションのディッピング効果が発生する場合がありますのでご注意ください。
      • Hard (旧名称:Spine Style 次のトラックをすぐに適用します。

Auto ResetとレイヤーのMix Modeパラメーターの結果

トランジションがアクティブになる際、現在のステートの最後のフレームセットアップポーズ前のクリップのポーズ新しいクリップのポーズ の4つのポーズがあり、これらは次のように組み合わされます :

  1. まず 現在のステートの最後のフレーム (またはSkeletonMecanimのupdate前のこのフレームの他の修正)で開始します。
  2. セットアップポーズ を適用します :
    • Auto Reset が有効な場合、セットアップポーズ現在のステートの最後のフレーム に置き換わります。
    • Auto Reset が無効な場合、セットアップポーズ はミックスに含まれません。

  3. 前のクリップのポーズ を適用します :
    • モードが Always Mix に設定されている場合は、前のクリップのポーズ が現在の状態とミックスされます (Auto Reset が有効な場合は セットアップポーズ とミックスされます)。
    • Hard または Mix Next に設定されている場合は、前のクリップのポーズ がフルウェイトで適用され、現在のステートよりも優先されます(つまり セットアップポーズ よりも優先されます)。

  4. 新しいクリップのポーズ を適用します :
    • モードが Always Mix または Mix Next に設定されている場合、新しいクリップのポーズは現在のステートとミックスされます。つまり、Auto Reset を有効にしている場合の Always Mix は、セットアップポーズ前のクリップのポーズ新しいクリップのポーズ が混合されます。
    • モードが Hard に設定されている場合、新しいクリップのポーズ はフルウェイトで適用され、以前に適用されたすべてのポーズよりも優先されます。

下の表は、前のクリップ P と新しいクリップ N の両方が同じタイムラインの値(例えば同じボーンの回転)を変更する場合を表しています。S は、Auto Reset が有効な場合はセットアップポーズを、無効な場合は現在のステート(例:前フレームのステート)を表します。トランジションウェイト(トランジション開始時に0、トランジション終了時に1)は、変数 w で表されます。各レイヤーのブレンドモードにおけるデフォルト(推奨)のミックスモードは、太字でハイライトされています。

Always Mix Mix Next Hard
Base Layer lerp(lerp(S, P, 1-w), N, w) lerp(P, N, w) N
Override lerp(
lerp(lower_layers_result,
P, (1-w) * layer_weight),
N, w * layer_weight)
lerp(
lerp(lower_layers_result,
P, layer_weight),
N, w * layer_weight)
lerp(lower_layers_result,
N,
layer_weight)
Additive lower_layers_result +
layer_weight * lerp(P, N, w))
counts as Always Mix lower_layers_result +
layer_weight * N
省略形 意味
S Setup pose(セットアップポーズ)
P Previous clip pose(前のクリップのポーズ)
N New clip pose(新しいクリップのポーズ)
w Transition weight(トランジションウェイト)
lerp(a, b, weight) Linear interpolation from a to b by weight (aからbへのウェイトによるリニア補間)

ControllerとAnimator

SkeletonMecanim コンポーネントは、UnityのMecanimと同様に Animator コンポーネントで割り当てられたControllerアセットを使用します。Controllerアセットはスケルトンをドラッグ&ドロップSkeletonMecanim としてインスタンス化する際に自動的に生成され、割り当てられます。

補足: Apply Root Motion を有効にすると、SkeletonMecanimRootMotionコンポーネントが SkeletonMecanim GameObjectに自動的に追加されます。

Controllerのアニメーションステートマシンにアニメーションを追加するには、SpineアニメーションをAnimatorパネルにドラッグ&ドロップします。アニメーションはControllerアセットの下にあります。

SkeletonDataAssetで設定されたMix duration値は、SkeletonMecanim では無視されます。代わりにAnimatorパネルで設定したMecanimのトランジションタイムが使用されます。

SkeletonMecanimイベント

SkeletonMecanim を使用する場合、イベントは各 AnimationClip に格納され、他のUnityのアニメーションイベントと同様に発生します。例えば、Spine内でイベント名を "Footstep" と命名した場合、SkeletonMecanim のGameObjectに MonoBehaviour スクリプトを用意し、Footstep() というメソッドを用意して処理する必要があります。Spine内でフォルダを使用している場合、メソッド名はフォルダ名とアニメーション名を連結したものになります。例えば、先ほどのイベントが Foldername というフォルダに入っている場合、FoldernameFootstep() となります。

C#
public class YourComponentReceivingEvents : MonoBehaviour {
   // フォルダの外に置かれてる場合にイベント"Footstep"をキャプチャするには
   void Footstep() {
      Debug.Log("Footstep event received");
   }

   // "Foldername"というフォルダの中に置かれている場合にイベント"Footstep"をキャプチャするには
   void FoldernameFootstep () {
      Debug.Log("Footstep (in folder Foldername) received");
   }
}

Unity Mecanimのイベントの詳細については、アニメーションイベントに関するUnityのドキュメントを参照してください。

SkeletonGraphicコンポーネント

SkeletonGraphicコンポーネントはUnityでSpineスケルトンを使用する3つの方法のうちの1つです。3つの方法とは、SkeletonAnimationSkeletonMecanimSkeletonGraphic (UI)のことです。

SkeletonGraphicコンポーネントはSkeletonAnimationコンポーネントの代わりに使用できるもので、レイアウト、レンダリング、マスクのインタラクションにUnityのUIシステムを使用します。SkeletonAnimationコンポーネントと同様に、SpineのスケルトンをGameObjectに追加し、アニメーションさせたり、アニメーションイベントに反応させたりすることができます。

なぜ特定のUIコンポーネントなのか

UnityのUI(UnityEngine.UI)は、CanvasCanvasRenderers システムを使って、レンダリング可能なオブジェクトを分類・管理しています。TextImageRawImage などの組み込みのレンダリング可能なUIコンポーネントは CanvasRenderer に依存して正しく機能します。MeshRenderers(例:デフォルトのCubeオブジェクト)や SpriteRenderers(例:Sprite)のようなオブジェクトをUIの下に置くと、Canvas ではレンダリングされません。SkeletonAnimationMeshRenderer を使用しているため、同様の挙動になります。そのため、spine-unityランタイムでは UnityEngine.UI.MaskableGraphic のサブクラスで CanvasRenderer コンポーネントをレンダリングに使用する SkeletonAnimation のvariantである SkeletonGraphic を提供しています。

マテリアルの重要な要件

SkeletonGraphicコンポーネントでは、デフォルトで割り当てられている Spine/SkeletonGraphic* シェーダーなど、CanvasRenderer互換の特殊なシェーダーを持つマテリアルのみを使用してください。URP、LWRP、Spine/Skeleton のような通常のシェーダーを SkeletonGraphic コンポーネントで使用しないでください。視覚的なエラーが出ないからといって、そのシェーダーが SkeletonGraphic で動作するとは限りません。実際、Unityエディター上では問題なくレンダリングできるのにモバイルデバイスでは正しくレンダリングできないという事例が確認されています。他のUIコンポーネントと同様に、SkeletonGraphicMeshRenderer ではなく CanvasRenderer を使用しており、別のレンダリングパイプラインを使用しています。

SpineAtlasAsset で割り当てられた通常のマテリアルは、SkeletonDataAssetSkeletonGraphic としてインスタンス化する際には無視され、テクスチャのみが使用されます。SkeletonGraphicCustomMaterials コンポーネントを使用すれば、SkeletonGraphic コンポーネントのマテリアルをオーバーライドすることができます。

重要な注意事項: Unityの CanvasRenderer の制限により、SkeletonGraphicはデフォルトでテクスチャの枚数が1枚だけに制限されています。SkeletonGraphic コンポーネントのInspectorで Advanced - Multiple CanvasRenderers を有効にすると、サブメッシュごとに 子 CanvasRenderer GameObject を生成して、テクスチャの枚数上限を上げることができます。ただし、パフォーマンス上の理由から、これは可能な限り避けた方が良いでしょう。つまり、UIで使用されるスケルトンは、複数ページのアトラスではなく、単一テクスチャー(単一ページ)のアトラスとしてパックされなければなりません。 アタッチメントを単一のアトラスページテクスチャにパックする方法については高度な情報 - 単一テクスチャアトラスのエクスポートとSkeletonGraphicをご覧ください。

正しい構成とマテリアル

"Spine/SkeletonGraphic Tint Black" のような特殊なシェーダーを使用したり、CanvasGroup以下で SkeletonGraphic を使用したりするには、それに応じて頂点データを生成する必要があります。関連するパラメーターは、Inspectorの Advanced - Vertex Data セクションにあります。設定するのは、Tint BlackCanvasGroup CompatiblePMA Vertex Color の3つです。各プロパティの横には Detect (検出)ボタンが用意されており、これを使って自動的に正しい設定を導き出せます。また、Detect Settings ボタンを使えば3つのプロパティすべての設定を検出できます。

Advanced - Vertex Data の設定を変更したら、アクティブな設定に合わせて使用するマテリアルを更新する必要があります。 SkeletonGraphic では、マテリアルはテクスチャから独立しているので、同じマテリアルプロパティを使用する異なるスケルトンで共有することができます。このため、主なパラメーターとシェーダーの組み合わせに対して、特別な共有SkeletonGraphicマテリアルが用意されています。選択した Advanced - Vertex Data 設定に対して適切なマテリアルは、Material プロパティの隣にある Detect ボタンを使って自動的に割り当てることができます。

スケルトンが複数のブレンドモードを使用していて Advanced - Multiple CanvasRenderers が有効になっている場合は、Blend Mode Materials の隣にある Detect ボタンを使用することで、同様の方法で適切なブレンドモードマテリアルを自動的に割り当てることができます。

正しくない結果が表示された場合は、アトラステクスチャのインポート設定が正しくない可能性があります(ドキュメントのこちらを参照してください)。

CanvasGroupアルファ

Spine/SkeletonGraphic* シェーダーを CanvasGroup で使用すると、以下の画像のように CanvasGroupAlpha 値 を減らすとスケルトンが明るくなってしまいます。

これは、水面下でUnityが頂点カラーのアルファ値を変更していることにより、残念ながらspine-unityランタイムの事前乗算アルファ(PMA)シェーダーではうまく再生できないためです。

重要な注意: spine-unity 4.2以降のランタイムには、Advanced - Vertex Data セクションのパラメーターに正しい設定を自動的に割り当てるための Detect ボタンと、アクティブな設定に基づいて適切なマテリアルを自動的に割り当てるための Detect Material ボタンが用意されています。そのため、詳細な情報が必要でない限り、以下のセクションは読み飛ばしてかまいません。

ティントブラック無しのSkeletonGraphicの場合

Spine/SkeletonGraphic TintBlack* 以外の Spine/SkeletonGraphic シェーダーでマテリアルを使用する場合は、以下が適用されます。このようなマテリアルをアルファフェードアウトを伴う CanvasGroup 以下で使用する場合、そのマテリアルは CanvasGroup Compatible パラメーターを有効にし、SkeletonGraphic コンポーネント PMA Vertex Colors を無効にする必要があります:

  1. a) spine-unityランタイムのバージョン4.2以降では、各マテリアルの CanvasGroup Compatible バリアントをそれぞれ Materials/SkeletonGraphic-PMATexture/CanvasGroupCompatible フォルダと Materials/SkeletonGraphic-StaightAlphaTexture/CanvasGroupCompatible フォルダで見つけられます。
    b) 古いバージョンでは、元のマテリアルを変更する代わりに、共有マテリアル SkeletonGraphicDefault のコピーを作成し、名前を SkeletonGraphic CanvasGroup などに変更するのが最善です。
  2. そしてこの CanvasGroup Compatible マテリアルを、CanvasGroup 以下の SkeletonGraphic コンポーネントに割り当ててください。
  3. この CanvasGroup 互換マテリアルを使用する SkeletonGraphic コンポーネントでは、半透明部分が二重に暗くなってしまうのを避けるために、Advanced - PMA Vertex Colors も無効にしておく必要があります。しかしこれを設定すると、残念ながら加算スロットを通常スロットと一緒にシングルバッチレンダリングすることができなくなるため、ドローコールが増えてしまう可能性があります。

SkeletonGraphic TintBlackの場合

同様に、Spine/SkeletonGraphic TintBlack シェーダーを使用しているマテリアルをアルファフェードアウトを伴う CanvasGroup 以下で使用する場合にも似たような設定が必要ですが、加算スロットの制限はありません。

  1. a) 上記と同様に、spine-unityランタイムのバージョン4.2以降では、CanvasGroupCompatible フォルダ内にある用意される SkeletonGraphic TintBlack マテリアルを使用してください。
    b) 古いバージョンでは、元のマテリアルを変更する代わりに、共有マテリアル SkeletonGraphicTintBlack のコピーを作成し、名前を SkeletonGraphicTintBlack CanvasGroup などに変更してください。この共有SkeletonGraphicマテリアルを作成する必要があるのは1度だけであり、使用するテクスチャに依存しないため、異なるスケルトンでも使用できることに注意してください。
  2. そしてこのマテリアルを CanvasGroup 以下の SkeletonGraphic コンポーネントに割り当てます。
  3. コンポーネントで Advanced - PMA Vertex Colors を無効にする必要はありませんので、このパラメーターは有効のままにしておいてください。 (バージョン4.1以前ではAdvanced - Canvas Group Tint Black)。
  4. a) spine-unity 4.2 以降を使用している場合、Advanced - PMA Vertex ColorsSkeletonGraphic 設定は、有効 / 無効の両方に対応しています。単一のドローコールで加算スロットをレンダリングできる利点があるため、Advanced - PMA Vertex Colors は有効にしておくことをお勧めします。 b) 古いバージョンでは、半透明の加算スロットが二重に暗くなるのを避けるために、Advanced - PMA Vertex Colors を無効にしてください。

境界と正しい表示

SkeletonGraphic の表示状態はRectTransformの境界によって決定されます。スケルトンが CanvasGameObjectの子としてドラッグ&ドロップでインスタンス化された場合はRectTransformの境界は自動的に初期ポーズにマッチします。また、Match RectTransform with Mesh ボタンをクリックすることで、RectTransformを現在のポーズの寸法に手動で合わせることもできます。RectTransformの境界がメッシュよりも小さくならないようにすることが重要です。そうしないと、例えば RectMask2D はメッシュの一部がまだ内側にあってレンダリングされるべきであるにもかかわらずRectTransformが外に出た時点でスケルトンの描画を省略してしまいます。現在のRectTransformの境界は、5つのトランスフォームモードのRectTransformツールがアクティブになっているときにSceneビューに表示されます。

パラメーター

SkeletonGraphic には、SkeletonAnimationコンポーネントと同様のパラメーターが用意されているので、そちらについての詳細はSkeletonAnimationセクションを参照してください。

SkeletonGraphic のInspectorは、以下の追加パラメーターを公開しています :

  • Material - Detect ボタン : Advanced - Vertex Data の設定に従って、適切な "Spine/SkeletonGraphic*" マテリアルを割り当てます。後述の Advanced セクションの Detect Material パラメータと同様です。

  • Freeze : trueに設定すると、SkeletonGraphicはアップデートされなくなります。

  • Layout Scale Mode : SkeletonGraphic は、RectTransform の境界に基づいた自動均一スケーリングに対応しています。デフォルトは None で、以前の動作を維持します。自動スケーリングは、このパラメーターを Width Controls HeightHeight Controls WidthFit In Parent または Envelope Parent (それぞれの詳細はこちらを参照)のいずれかに設定することで有効にすることができます。参照レイアウト境界を変更するには、 Edit Layout Bounds トグルボタンを押して編集モードに入り、スケルトンの境界を調整することができます。スケルトンは、参照レイアウト境界をオブジェクトの RectTransform に合わせて、適宜スケーリングされます。

  • Edit Layout Bounds : 上記の Layout Scale Mode で使用される参照レイアウト境界を変更するには、このトグルボタンを押して編集モードにします。その後、手動で境界を調整するか、 Match RectTransform with Mesh を押して、現在のポーズに合わせることができます。調整が完了したら、 Edit Layout Bounds トグルボタンをもう一度押して、編集モードを終了します。

  • Match RectTransform with Mesh : Match ボタンをクリックすると SkeletonGraphic のRectTransformを現在のポーズの寸法に合わせることができます。RectTransformの境界がメッシュよりも小さくならないようにすることが重要です。そうしないと、例えば RectMask2D は、メッシュの一部がまだマスクの内側にあってレンダリングされるべきであったとしても、RectTransformが外に出た時点でスケルトンの描画を省略してしまいます。Layout Scale ModeNone に設定されているか、Edit Layout Bounds トグルボタンがedit-modeに設定されていない限り、このオプションはグレーアウトされます。

  • Advanced

    • Use Clipping : false に設定すると、いかなるSpineのクリッピング・アタッチメントも無視されるようになります。

    • Tint Black (!) : メッシュにブラックティント頂点データを追加します。スケルトンにティントブラックカラーが設定されたスロットがある場合は有効にしてください。
      ブラックティントは、提供されている Spine/SkeletonGraphic Tint Black* シェーダーのように、シェーダーが UV2 と UV3 をブラックティントカラーとして解釈する必要があります。 親Canvasで UV2 と UV3 データを許可するには、そのCanvasを選択し、Additional Shader ChannelsTexCoord1TexCoord2 を有効にする必要があります。

      SkeletonDataにティントブラックが設定されているスロットがあればこのパラメーターを有効にし、そうでなければ無効にする Detect ボタンが用意されています。

    • CanvasGroup Compatible : SkeletonGraphic が CanvasGroup GameObject の下で使用されている場合は有効にしてください。マテリアルも CanvasGroup Compatible を有効にする必要があるので、Detect Material を使うか、または手動でこの設定を変更した後に適切なマテリアルを割り当ててください。
      SkeletonGraphic Tint Black* シェーダーを使用していて、Tint BlackPMA Vertex Color の両方が有効になっている場合、アルファ値はプライマリ頂点カラー color.a ではなく uv2.g に保存され、color.acolor.a を変更する CanvasGroup を捕捉するために定数 1.0 を保存します。

      階層内でSkeletonGraphicコンポーネントがCanvasGroupコンポーネントの下にあるならこのパラメータを有効にし、そうでない場合は無効にする Detect ボタンが用意されています。

    • [4.1以前のバージョンのみ] Canvas Group Tint Black : これは SkeletonGraphic Tint Black シェーダーを使用する場合のみ有効にしてください。Tint Black が無効の場合、または PMA Vertex Color が無効な場合は効果がありません。CanvasGroup の下にある SkeletonGraphic のスロットで Additive ブレンドモードを使用する場合に有効にしてください。有効にすると、アルファ値はプライマリ頂点カラー color.a の代わりに uv2.g に格納され、color.a は、color.a を変更する CanvasGroup を捕捉するために定数 1.0 を保存します。

    • PMA Vertex Colors (CanvasGroupアルファ用の追加ルール) : 頂点カラーRGBと頂点カラーアルファを乗算します。このパラメーターはデフォルトで有効になっており、サードパーティ製のシェーダーを使用する場合や CanvasGroup Compatible を有効にする必要がある場合を除き、そのままにしておくのが正しい設定です。具体的には以下のルールが適用されます:

      Detect ボタンが用意されていますが、これは Tint BlackCanvasGroup Compatible が正しく設定されている必要があります。Detect は、サードパーティー製(つまりSpineに付属しているもの以外)のシェーダーが使用されている場合、または CanvasGroup Compatible が有効で Tint Black が無効の場合、このパラメーターを無効にします。それ以外の場合はこのパラメーターを有効にします。

      具体的には以下のルールが PMA Vertex Color に適用されます (これが必要なのはDetect がうまくいかなかった時のみです):

      spine-unity 4.2以降を使用している場合:
      このパラメーターを有効にする必要がある場合 (デフォルト):

      • 使用する "Spine/SkeletonGraphic*" シェーダーで CanvasGroup Compatible が無効になっている場合(Straight Alpha Texture が有効になっている場合でも)。または
      • "Spine/SkeletonGraphicTintBlack*" シェーダーを使用している場合(Straight Alpha Texture が有効になっている場合でも)。または
      • PMAとして頂点カラーを必要とするサードパーティー製(つまりSpineに付属しているもの以外)のシェーダーを使用している場合。(そのシェーダーが、PMA加算出力ブレンドモード Blend One OneMinusSrcAlpha を使用している場合など。)

      このパラメーターを無効にする必要がある場合:

      • "Spine/SkeletonGraphicTintBlack*" は使用していなくて、通常の "Spine/SkeletonGraphic*"シェーダーで CanvasGroup Compatible が有効になっている場合。または
      • 通常の頂点カラーを必要とするサードパーティー製(つまりSpineに付属しているもの以外)のシェーダーを使用している場合。(そのシェーダーが、通常出力ブレンドモード Blend SrcAlpha OneMinusSrcAlpha で使用している場合など。)

      spine-unity 4.1以前を使用している場合:
      このパラメーターを有効にする必要がある場合 (デフォルト):

      • 使用する "Spine/SkeletonGraphic*" シェーダーで CanvasGroup Compatible が無効になっている場合(Straight Alpha Texture が有効になっている場合でも)。または
      • PMAとして頂点カラーを必要とするサードパーティー製(つまりSpineに付属しているもの以外)のシェーダーを使用している場合。(そのシェーダーが、PMA加算出力ブレンドモード Blend One OneMinusSrcAlpha を使用している場合など。)

      このパラメーターを無効にする必要がある場合:

      • "Spine/SkeletonGraphic*" シェーダーを使用していて CanvasGroup Compatible が有効になっている場合。または
      • 通常の頂点カラーを必要とするサードパーティー製(つまりSpineに付属しているもの以外)のシェーダーを使用している場合。(そのシェーダーが、通常出力ブレンドモード Blend SrcAlpha OneMinusSrcAlpha で使用している場合など。)

      有効にすると、加算スロットは通常スロットと一緒に1回のドローコールでレンダリングできます。無効にすると、加算スロットのためにSkeletonDataBlend Mode Materials - Apply Additive Material を有効にする必要があり、それによって別のドローコールが必要になってしまうため、パフォーマンスに悪影響を与える可能性があります。

    • Detect Settings: Tint BlackCanvasGroup CompatiblePMA Vertex Colors の適切なパラメーターの検出を一度に適用します。

    • Detect Material: 上記の Tint BlackCanvasGroup Compatible パラメーターとアトラステクスチャのインポート設定(PMA設定なのかストレートアルファ設定なのか)に基づいて、適切な SkeletonGraphic マテリアルを割り当てます。正しくない結果が表示された場合は、テクスチャの設定が正しくない可能性があります(詳しくはドキュメントの こちらを参照してください)。

    • Multiple CanvasRenderers : true に設定すると、SkeletonGraphic は1つの CanvasRenderer を使用せず、必要なドローコール(サブメッシュ)ごとに、必要な数の 子CanvasRenderer GameObjectを自動的に作成します。これにより、単一テクスチャの制限を緩和することができますが、パフォーマンスのオーバーヘッド(処理負荷)が発生します。

      • Blend Mode Materials : スロットのブレンドモードごとに異なる SkeletonGraphic マテリアルを使用できるようにします。ただしここでは、"Spine/SkeletonGraphic *" または他のCanvasRenderer互換のマテリアルのみを使用してください。

      • Assign Default を選択すると、デフォルトのブレンドモードマテリアル SkeletonGraphicAdditiveSkeletonGraphicMultiplySkeletonGraphicScreen が割り当てられます。

        注意: SkeletonGraphicBlend Mode Materials の割り当ては SkeletonDataAsset のマテリアルに依存しているため、SkeletonDataAsset でブレンドモードマテリアルが適切に設定されていることを確認してください。PMA Vertex Colors が有効な場合、Additive Material は無視されます。

  • Animation Update : 通常の Update (デフォルト)、物理ステップ FixedUpdate、またはユーザーコールによる手動アニメーション更新のいずれかを指定します。Rigidbody または Rigidbody2D が割り当てられたSkeletonRootMotion コンポーネントを使用する場合、更新モードを In FixedUpdate に設定することをお勧めします。それ以外の場合は、In Update を推奨します。

    • Update When Invisible : MeshRendererが非表示になった時に使用されるUpdateモードです。メッシュが再び表示されるようになると、Updateモードは自動的に UpdateMode.FullUpdate にリセットされます。

    • Separator Slot Names : Enable Separationtrue に設定されているときに、レンダリングを分割する場所を決定するスロットです。レンダリングの分割に関する全般的な情報はSkeletonRenderSeparatorセクションを参照してください。ただし SkeletonGraphic においては追加のコンポーネントは必要ありません。

    • Enable Separation : レンダリングの分割は、このInspectorセクションで直接有効にすることができ、追加のコンポーネント(SkeletonRenderSeparatorSkeletonRenderer コンポーネントの SkeletonPartsRenderer など)は必要ありません。有効にすると、追加の分割されたGameObjectが自動的に作成され、それに応じて CanvasRenderer GameObjectが再ペアリングされます。分割されたGameObjectは、必要に応じて階層内で移動させたり再配置したりして Canvas 内での望ましい描画順序を実現することができます。

    • Update Part Location : 有効にすると、分割されたGameObjectの位置が SkeletonGraphic の位置に合わせて更新されます。これは、パーツを別のGameObjectに再ペアリングしたい場合に役立ちます。

    • Physics Inheritance : トランスフォームの動きをスケルトンの物理コンストレイントに適用する方法を制御します。

      • Position : ゼロ以外に設定すると、X方向およびY方向のトランスフォームの位置移動がスケルトンの物理コンストレイントに適用され、ここで設定したXおよびYのスケール係数で乗算されます。一般的な組み合わせは以下の通りです:
        (1,1) にした場合、XY移動が通常通り適用されます。
        (2,2) にした場合、XY移動が倍の強さで適用されます。
        (1,0) にした場合、水平方向の移動だけが適用されます。
        (0,0) にした場合、トランスフォームの移動の動きは全く適用されなくなります。
      • Rotation : ゼロ以外に設定すると、トランスフォームの回転の動きがスケルトンの物理コンストレイントに適用され、ここで設定したスケール係数で乗算されます。一般的な値は以下の通りです:
        1 にした場合、通常通り適用されます。
        2 にした場合、倍の強さで適用されます。
        0 にした場合、トランスフォームの回転の動きは全く適用されなくなります。

サンプルシーン

基本的な使用方法については、Spine Examples/Getting Started/6 Skeleton Graphicにあるサンプルシーンで確認することができます。 また、Separator Slotを設定したり、描画順序を変更する方法を紹介している高度なサンプルシーンは、Spine Examples/Other Examples/SkeletonRenderSeparator で確認できます。

SkeletonRendererコンポーネント

SkeletonRenderer コンポーネントは、スケルトンの現在のステートを描画する役割を担っています。これはSkeletonAnimationSkeletonMecanimの基底クラスとなっています。

補足: ほとんどの場合、代わりにSkeletonAnimationSkeletonMecanimSkeletonGraphic (UI)のいずれかを使用することになるでしょう。これらのコンポーネントは、アニメーションを制御する高度な手段を提供します。UIのゲージ要素のように、トランジションなしで手動でアニメーションを適用したい場合に限り、このコンポーネントはそのままで役立ちます。

レンダリングは、MeshRendererコンポーネントで更新されるプロシージャルメッシュによって行われます。このコンポーネントはSkeletonDataAssetによって参照されるテクスチャアトラスアセットを使用して、スケルトンのアタッチメントを描画するのに必要なテクスチャとマテリアルを見つけます。詳細はSkeletonAnimationセクションを参照してください。

SkeletonRenderer コンポーネントを直接使用する方法については、サンプルシーンの Spine Examples/Other Examples/SpineGauge で確認できます。

次: ユーティリティコンポーネント 前: アセット