コンテンツへスキップ

QualiArtsengineer blog

大量のSD制作を支える「IDOLY PRIDE」におけるSpine活用事例① 〜導入/方向制御編〜

大量のSD制作を支える「IDOLY PRIDE」におけるSpine活用事例① 〜導入/方向制御編〜

9 min read

はじめに

株式会社QualiArtsでUnityエンジニアをしている吉成です。2021年6月リリースの「IDOLY PRIDE」(以降、アイプラ)の開発に携わり、主にUnityでのゲーム開発やSD周りの設計を担当しています。

アイプラには数多くのキャラクターや衣装が存在します。 現在、SDが実装されているキャラクターは20名。そしてそれぞれのキャラクターに対して様々な衣装が存在しており、キャラクターと衣装の組み合わせは全部で232種類となります。 また、それぞれの衣装に必要なSDモーションは90個存在し、単純計算で作成するべきモーション数は20,880個となります。

これは単純作業で制作を行うのは不可能な物量であり、アイプラでは作業を減らして効率的な制作を行うための工夫を意識しました。 また、アイプラではSpineを用いてSDの制作を行っております。

今回は3回に渡って、アイプラにおけるSpineの活用事例を紹介していきます。

  1. 導入/方向制御編
  2. アイテム付与/モーション合成編
  3. バリエーションの実現/データ分割編

第1回目となる本記事では『導入/方向制御編』として、簡単なSpineの紹介と、効率的な制作を行うために行ったキャラクターの方向制御周りでの工夫点の紹介を行います。

Spineの実務ベースでの利用法の話は情報が少なく、自分も今回の制作では苦労したため、本記事が少しでも皆さまのゲーム制作の参考になれば幸いです。

Spineの紹介

Spineとはゲーム向けの2Dアニメーションツールです。

spine logo

Spineはアニメーションの制作とゲームへのアニメーションの組み込みをサポートしています。ゲーム向けとなっているものの、リッチな演出制作などで幅広く利用することができます。 また、Unity、UnrealEngine、cocos2d-xだけでなくWebなどもサポートしており、幅広い環境で利用することもできます。

Spineは次の3つの要素で構成されています。

  1. Atlasテクスチャ
  2. Atlasテキスト
  3. SkeletonDataファイル

まずはこの3つの要素をそれぞれ説明します。

Atlasテクスチャ

Atlasテクスチャはアトラスのテクスチャです。 説明がそのまま過ぎるので画像を見ていただいた方がイメージが付きやすいと思います。 このテクスチャ内のパーツを組み合わせることでSpineでの描画を行います。

atlas

Atlasテキスト

Atlasテキストはアトラス情報の書かれたテキストです。 こちらにAtlasテクスチャの切り抜き方などが定義されています。

spi_sd_chr_cos_skr-idol-01.png
size: 2048,2048
format: RGBA8888
filter: Linear,Linear
repeat: none
chara/Ex_body_n_1@FL
  rotate: false
  xy: 2035, 1587
  size: 1, 1
  orig: 1, 1
  offset: 0, 0
  index: -1
chara/Ex_body_n_1@FR
  rotate: false

SkeletonDataファイル

SkeletonDataファイルは骨格情報の書かれたファイルです。 ボーンやアニメーション、それに付随するスキン情報などが定義されています。 SkeletonDataファイルはjson形式かバイナリ形式かを選択することができます。

{
    "skeleton" : {  },
    "bones" : {  },
    "slots" : {  },
    "ik" : {  },
    "transform" : {  },
    "path" : {  },
    "skins" : {  },
    "events" : {  },
    "animations" : {  },
}

3要素の組み合わせ

以上の3要素を組み合わせることで、Unity上でSDを生成することができます。 また、Spineからエクスポートされたアニメーション可能なキャラクターやオブジェクトはスケルトンと呼ばれます。

create simple sd

方向制御

次に方向制御周りの話をします。

まずは違和感を感じる箇所が無いかを意識しつつ、千紗のダンスモーションを見てみましょう。

反対を向いた際に、髪型(頭)が反転してしまっていることが分かると思います。

頭が反転してしまった原因は頭の方向転換の方法にあります。

今回、頭を左右反転することで頭の方向転換を実現しています。 しかし単純に反転をしただけだと絵柄自体も反転してしまいます

chs head

そしてそれは頭だけでなく身体の方向についても同様です。 つまり、左右非対称の服も考慮すると4つのパターンを用意する必要があります。
※今回キャラクターは後ろを向かない仕様になっています。

単純に反転をすると次のようになってしまいます。

chs head body

それぞれ本当は次のようになって欲しいです。

chs head body true

これを実現するために、各々のSDに対して4パターンのSpineを別々に用意するのは避けたいです。

スキン切り替えによる反転対応

Spineのスキン機能を用いることにより、上記の要望を実現します。 スキン機能を用いると、割り当てるテクスチャを変更することができるようになります。

今回は左右非対称のパーツに関しては、右向きと左向きのテクスチャをそれぞれ用意し、状況に応じて適切なスキンを設定し、適切なテクスチャを割り当てるようにしました。

例えば、今回の千紗のデザインだと、後ろ髪は反転が問題ないので1つだけパーツを用意します。

chs single

そして、前髪、前髪の影が落ちた顔、服、などの左右非対称で単純に反転して使えないパーツに関しては、左右が反転しているパーツも用意します。

chs double

実際に千紗のAtlasテクスチャを見てみると、左右非対称のパーツのみ複数のパーツが用意されていることが分かります。

atlas chs

そして、左右非対称のパーツを反転させる際には、そもそも左右が反転しているパーツを付けてから、左右の反転を行います。 これにより、反転したものが反転され、パーツの左右の向きが正しくなります。

chs reverse flow

それではスキンの指定方法を見ていきます。 SpineからエクスポートされたスケルトンをUnity上で表示やアニメーションさせるためのコンポーネントとして、SkeletonAnimationというコンポーネントがあります。スキンの変更はSkeletonAnimationコンポーネント内のSkeletonから行います。

まず、スキンが1つだけの場合はSkeletonにスキン名を設定するだけでOKです。

skeletonAnimation.Skeleton.SetSkin("skinName");

今回は頭と身体でスキンを分ける必要があるため、この手法を用いることはできません。 例えば次の状態だと、頭には右向きのスキンを適用する必要があり、身体には左向きのスキンを適用する必要があります。

chs skin

スキンが複数の場合は、次の方法でスキンを指定することができます。

void ChangeSkins(Skeleton skeleton, IList<string> skinNames)
{
    // 結合用のSkinを生成
    var combinedSkin = new Skin("CombinedSkin");
    if (skinNames != null)
    {
       // 結合用のSkinに対象のSkinを割り当てていく
        for (var i = 0; i < skinNames.Count; i++)
        {
            var skinName = skinNames[i];
            var skin = skeleton.Data.FindSkin(skinName);
            if (skin == null) continue;
            combinedSkin.AddAttachments(skin);
        }
    }
    // 結合用のSkinを設定し、反映用の処理を叩く(←大事)
    skeleton.SetSkin(combinedSkin);
    skeleton.SetSlotsToSetupPose();
}

そして今回はhead(頭)とbody(身体)のそれぞれにFL(FrontLeft:左前)とFR(FrontRight:右前)のスキンを用意しました。

chs table

そして頭が右向き、体が左向きのスキンは次のコードで設定することができます。

ChangeSkins(skeletonAnimation.Skeleton, new List<string>() { "head_FR", "body_FL" });

これでスキンの変更方法は分かりました。しかしまだどのタイミングでスキンを切り替えれば良いのかは分かりません。

モーションのイベント設定によるスキン切り替えタイミングの取得

スキンを切り替えるタイミングの検知には、モーションのイベント設定を利用します。 Spineではモーションにイベントを設定することが可能です。今回は4つのイベントを用意しました。

イベント名イベント発生時の処理
flip_head_FL頭のスキンをhead_FLに変更(頭を左向きに変更)
flip_head_FR頭のスキンをhead_FRに変更(頭を右向きに変更)
flip_body_FL身体のスキンをbody_FLに変更(身体を左向きに変更)
flip_body_FR身体のスキンをbody_FRに変更(身体を右向きに変更)

そして、イベントは次の方法で監視をすることが可能です。

// イベントの監視
skeletonAnimation.AnimationState.Event += OnAnimationEvent;

// イベントが発生するたびに呼ばれる
void OnAnimationEvent(TrackEntry t, Event e)
{
    if (e.Data.Name == "flip_head_FL")
    {
        // スキンをhead_FLに変更
        return;
    }

    if (e.Data.Name == "flip_head_FR")
    {
        // スキンをhead_FRに変更
        return;
    }
// ・・・以下略
}

発火したイベント名に応じて処理を実行しています。 また、イベントに設定した値はe.Data.Inte.Data.Floate.Data.Stringなどで取得可能です。

以上を踏まえたモーションが次のモーションとなります。

このモーションは最初に左向きで開始するために、1フレーム目にflip_head_FLflip_body_FLのイベントが設定されており、頭が右を向くタイミングでflip_head_FR、頭が再度左を向くタイミングでflip_head_FLのイベントが設定されています。

これにより、反転が起こらなくなりました。

これで完璧!と言いたいところなのですが、まだ課題があります。

左右のモーションの使いまわし

左右それぞれに走るモーションを見てみましょう。

まずは向きごとのモーションを別々に作ることを考えてみます。

左向きに走るモーションは1フレーム目にflip_head_FLflip_body_FLのイベントを設定し、右向きに走るモーションは1フレーム目にflip_head_FRflip_body_FRのイベントを設定してモーションを作成すれば良いです。

しかし走るモーションを詳しく見てみると、実際この2つのモーションはほぼ同じです。動きは左右反転しているだけで、スキンも左右が入れ替わっているだけです。 そのため左右それぞれでモーションを作るのはもったいないです

そこで左右それぞれでモーションを作らないで済むように、モーションを1つで済ます方法を考えます。

今回は、モーションは全て左向きだけを作成するようにし、右向きにしたい時は、使う側で左右を反転するようにしました。 そして左右を反転したら、逆側のスキンを設定するようにしています。

最終的な走るモーションは、左向きに走るモーションは元のまま1フレーム目にflip_head_FLflip_body_FLのイベントを設定しています。 そしてモーションを右向きに変更する際には、左右を反転し、スキンも反転させ、モーション自体にはflip_head_FLflip_body_FLのイベントが設定されているのですが、逆のスキンであるhead_FRbody_FRを設定するようにしています。

これにより左右それぞれでモーションを作らないで済むようになりました。

方向制御まとめ

左右非対称のパーツは反転用のテクスチャも用意しました。 そして反転時のテクスチャはスキンで切り替え、反転させるタイミングはモーションにイベントとして設定をしました。

また、左右のモーションは片側だけ作成して使いまわしました。 反対向きのモーションとして再生したい際は左右を逆転させ、その際、スキンも設定されている方向からさらに逆転をさせました。

おわりに

簡単なSpineの紹介と、効率的な制作を行うために行ったキャラクターの方向制御周りでの工夫点の紹介を行いました。

次回は『アイテム付与/モーション合成編』として、キャラクターにアイテムを持たせるために行った工夫や、モーションを効率的に作成するために行ったモーション合成の方法の紹介を行います。

2013年にサイバーエージェントに新卒入社。QualiArtsにてUnityエンジニアとして複数のゲームの開発・運用に携わる。現在は、ゲーム・エンターテイメント事業部(SGE)のエンジニアボードとして、事業部全体のエンジニアの新卒採用と若手育成および組織作りも行っている。著書:『ステップアップUnity プロが教える現場の教科書』