おもちゃラボ

Unityで遊びを作ってます

【Unity】Anima2Dでユニティちゃんがネギを振るアニメを作る

Anima2Dとは2Dのキャラクタでスケルタルアニメーション(ボーンアニメーション)を作るためのツールです。
Anima2Dを使うことで、ボーンに従ったアニメーションが作れるほか、メッシュを変形させたり、IK(Inverse Kinematic)を使うこともできます。


https://www.assetstore.unity3d.com/jp/#!/content/79840

これまでSpineSpriterといったようなツールがありましたが、どちらも有償でした。Anima2DはUnityTechnologies社から無償で提供されるので、ぐっと敷居が下がりましたね〜!

今回はユニティちゃんがネギを振るアニメーションを作りながらAnima2Dの使い方を学んでいきましょう。

Anima2Dを使用するための下準備をする

Anima2Dでアニメーションさせるためのスプライトは、一つのスプライトにまとめて(スプライトパック)おく必要があります。ここでは次のようなスプライトを用意しました。

f:id:nn_hokuson:20170309191246p:plain

このスプライトをプロジェクトビューにドラッグ&ドロップし、インスペクタから「Sprite Mode」を「Multiple」にします。

f:id:nn_hokuson:20170309191903p:plain:w250

続いてSprite Editorのボタンを押し、Sprite Editorで「Slice」ボタンを押してスプライトを自動で分割し、Applyボタンを押してください。

f:id:nn_hokuson:20170309191907g:plain

プロジェクトビューに戻り、ユニティちゃんのスプライトを選択した状態で右クリックから「Create」→「Anima2D」→「SpriteMesh」を選択します。Sprite Meshオブジェクトが3つ作成されます。

f:id:nn_hokuson:20170309191927p:plain:w300

スプライトとボーンを組み立てる

いま作成したSpriteMeshをシーンビューにドラッグ&ドロップしていい感じに配置しましょう。
ヒエラルキービューで空のオブジェクトを作成し、その子要素としてSpriteMeshを配置しています。
それぞれのスプライト名はBody、Arm、Negiに変更しました。

f:id:nn_hokuson:20170309191934p:plain:w450

スプライトの重なり順はインスペクタの「Order in Layer」から変更します(後から出てくるボーンの設定からも変更できます)

次にボーンを作ります。ヒエラルキービューでunitychanを選択し、右クリックから「2D Object」→「Bone」を選択します。
unitychanオブジェクトの子要素として画面上にボーンが作成されます。
インスペクタでボーンの長さと位置を調節して、ユニティちゃんの体の上に配置します。

f:id:nn_hokuson:20170309194047p:plain:w450

続いて、いま作成したボーンの子要素となるように腕のボーンを作ります。ヒエラルキービューでいま作成したボーンを選択して右クリックし、ボーンを作ってください。作成したボーンは腕付近に移動します。

同様の手順で、腕のボーンの子要素としてネギのボーンを作成します。それぞれのボーンの名前はBodyBone、ArmBone、NegiBoneにしました。

f:id:nn_hokuson:20170309191948p:plain:w450

スプライトとボーンを関連付ける

今はボーンをスプライトの上に配置しただけなので、ボーンを動かしても当然スプライトは移動しません。ボーンとスプライトが連動して移動するように、関連付けを行いましょう。

f:id:nn_hokuson:20170309191955g:plain

Bodyのインスペクタから「Sprite Mesh Instance」→「Bones」→「+」を押してください。ボーンを設定する欄が出てくるので、ここにヒエラルキービューから「BodyBone」をドラッグ&ドロップしてください。

f:id:nn_hokuson:20170309192005g:plain

同様に、ArmとnegiのスプライトにもArmBoneとNegiBoneを設定します。

ボーンの重み付けをする

ボーンとスプライトの重み付けを行います。「Window」→「Anima2D」→「SpriteMesh Editor」を起動してください。

ヒエラルキービューでBodyを選択するとエディタにBodyとBodyBoneが表示されます。この状態でBindボタンを押して、Weight tool ウインドウからOverlayにチェックを入れてAutoボタンを押してください。

f:id:nn_hokuson:20170309192019g:plain

これで、BodyのスプライトとBodyBoneのボーンが関連付けられました。同様の手順で、ArmとArmBone、NegiとNegiBoneを関連付けましょう。
シーンビューでボーンを動かすとスプライトもそれにともなって動くようになりました。

f:id:nn_hokuson:20170309192034g:plain

ネギを振るのアニメーションを作ろう

最後にユニティちゃんがネギをふるアニメーションを作りましょう。

まずはユニティちゃんオブジェクトを選択した状態で、「Window」→「Animation」を選択します。Animationウインドウから「Create」ボタンを押して「swing@unitychan」という名前のファイルを作ります。

f:id:nn_hokuson:20170309192050p:plain

Enable Recordingボタンが有効(再生ボタンが赤色)になっていることを確認しましょう。
タイムラインのカーソルを0フレーム目に移動し、腕を少し下げた位置に移動してください。これで0フレーム目にキーが打たれます。

f:id:nn_hokuson:20170309192058g:plain

次にタイムラインを20フレーム目に移動し、ボーンを回転させて腕を振り上げます。

f:id:nn_hokuson:20170309192106g:plain

最後に0フレーム目のキーフレームをコピーして40フレーム目の位置にペーストします。これでネギを振る一連のアニメーションが完成しました。

f:id:nn_hokuson:20170309192121p:plain

できたアニメーションは次のようになります。

f:id:nn_hokuson:20170309192128g:plain

まとめ

今回はUnityが無料で配布しているAnima2Dの使い方を紹介しました。Anima2Dを使えば、簡単にスケルタルアニメーションが作れました。
Anima2Dには、ここでは紹介できなかった機能がまだまだたくさんあるので、また紹介したいと思います。

今回もテラシュールブログさんの記事を参考にさせていだきました〜m(_ _)m
tsubakit1.hateblo.jp

この作品はユニティちゃんライセンス条項の元に提供されています
© Unity Technologies Japan/UCL

【OpenGLでゲームを作る】複数のテクスチャを表示する

前回はようやく四角形のポリゴンにテクスチャを貼り付けることができました。

nn-hokuson.hatenablog.com

通常、ゲームを作るときには一枚のテクスチャを使うのではなく、複数毎のテクスチャを使います。
そこで、今回はテクスチャを2枚表示するサンプルを作ってみましょう。

複数枚のテクスチャを表示する流れ

複数枚のテクスチャを表示する流れは、テクスチャを一枚表示する流れと変わらず、表示したいテクスチャの枚数ぶん下記の処理を繰り返します。

  1. テクスチャの読み込み
  2. テクスチャをGPUにアップロード
  3. 座標情報、UV情報をシェーダに渡す
  4. 使用するテクスチャのバインド
  5. 描画する

f:id:nn_hokuson:20170308205156p:plain:w550

複数枚のテクスチャを表示するプログラム

今回のプログラムは次のようになります。シェーダの内容やテクスチャの読み込みプログラムに変更はないので、main関数のみを載せています。
ソースコード全文はGitHubをご確認ください。

ソースコード全文はこちら
multiTexture.cpp · GitHub

int main()
{
    if( !glfwInit() ){
        return -1;
    }
    
    GLFWwindow* window = glfwCreateWindow(g_width, g_height, "Simple", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }
    
    // モニタとの同期
    glfwMakeContextCurrent(window);
    glfwSwapInterval(1);
    
    GLuint programId = crateShader();
    
    GLuint catTexID = loadTexture("cat.raw");
    GLuint skyTexID = loadTexture("sky.raw");
    
    // ゲームループ
    while (!glfwWindowShouldClose(window)) {
        
        // 画面の初期化
        glClearColor(0.2f, 0.2f, 0.2f, 0.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glClearDepth(1.0);
        
        
        const GLfloat vertex_uv[] = {
            1, 0,
            0, 0,
            0, 1,
            1, 1,
        };
        
        // 何番目のattribute変数か
        int positionLocation = glGetAttribLocation(programId, "position");
        int uvLocation = glGetAttribLocation(programId, "uv");
        int textureLocation = glGetUniformLocation(programId, "texture");
        
        // attribute属性を有効にする
        glEnableVertexAttribArray(positionLocation);
        glEnableVertexAttribArray(uvLocation);

        // uniform属性の登録
        glUniform1i(textureLocation, 0);

        // 1枚目
        {
            // 頂点データ
            float vertex_position[] = {
                0.0f, 0.5f,
                -1.0f, 0.5f,
                -1.0f, -0.5f,
                0.0f, -0.5f
            };
            
            // attribute属性を登録
            glVertexAttribPointer(positionLocation, 2, GL_FLOAT, false, 0, vertex_position);
            glVertexAttribPointer(uvLocation, 2, GL_FLOAT, false, 0, vertex_uv);
          
            // モデルの描画
            glBindTexture(GL_TEXTURE_2D, catTexID);
            glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
        }
        
        // 2枚目
        {
            // 頂点データ
            float vertex_position[] = {
                1.0f, 0.5f,
                0.0f, 0.5f,
                0.0f, -0.5f,
                1.0f, -0.5f
            };
            
            // attribute属性を登録
            glVertexAttribPointer(positionLocation, 2, GL_FLOAT, false, 0, vertex_position);
            glVertexAttribPointer(uvLocation, 2, GL_FLOAT, false, 0, vertex_uv);
            
            // モデルの描画
            glBindTexture(GL_TEXTURE_2D, skyTexID);
            glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
        }
              
        // バッファの入れ替え
        glfwSwapBuffers(window);
        
        // Poll for and process events
        glfwPollEvents();
    }
    
    glfwTerminate();
    
    return 0;
}

実行結果は次のようになります。

f:id:nn_hokuson:20170308203829j:plain:w350

続けて複数枚テクスチャの表示プログラムを解説していきます。
テクスチャの表示の詳細については、次の「マルチプラットフォームのためのOpenGL ES入門 基礎編」で丁寧に解説されているので参考にしてみてください。

プログラムの解説

今回は猫のテクスチャと水のテクスチャを使いたいので、loadTexture関数を使って2つのファイルを読み込んでGPUにアップロードしています。
猫と水のテクスチャは、それぞれcatTexIDとwaterTexIDという変数で管理します。

GLuint catTexID = loadTexture("cat.raw");
GLuint waterTexID = loadTexture("water.raw");

各テクスチャとテクスチャIDの対応は次のようになります。

f:id:nn_hokuson:20170308212457p:plain:w300

シェーダとの変数のやりとり部分は前回と変わりありません。glGetAttribLocation関数を使ってattribute変数の位置を教えてもらい、glEnableVertexAttribArrayで指定したattribute変数を有効化しています。Uniform変数も同様の手順で有効化しています。

続いて1枚目のテクスチャを描画する部分です。最初にポリゴンの頂点座標を指定しています。ここでは画面左半分にポリゴンを表示するように、座標を指定しています。

// 頂点データ
float vertex_position[] = {
     0.0f, 0.5f,
     -1.0f, 0.5f,
     -1.0f, -0.5f,
     0.0f, -0.5f
};

続いてglVertexAttribPointer関数を使って座標情報とテクスチャのUV情報をシェーダに送ります。UV情報は1枚目のテクスチャも2枚目のテクスチャも変わらないので共用で使用しています。

// attribute属性を登録
glVertexAttribPointer(positionLocation, 2, GL_FLOAT, false, 0, vertex_position);
glVertexAttribPointer(uvLocation, 2, GL_FLOAT, false, 0, vertex_uv);

最後にテクスチャを描画します。まずは描画したいテクスチャをバインドします。
描画したいテクスチャはテクスチャIDで指定します。ここでは猫のテクスチャを描画したいのでglBindTexture関数にcatTexIDを渡しています。

f:id:nn_hokuson:20170308212728p:plain:w300

最後にglDrawArraysでGPUに描画命令を出しています。

// モデルの描画
glBindTexture(GL_TEXTURE_2D, catTexID);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

今の手順と全く同様の手順で2枚目のテクスチャも描画します。
異なっているのは、画面右半分に四角形のポリゴンを描くように座標設定していることと、glBindTextureでバインドするテクスチャIDをwaterTexIDを指定している部分です。これにより、画面右半分には水のテクスチャが表示されます。

f:id:nn_hokuson:20170308212900p:plain:w300

// 頂点データ
float vertex_position[] = {
    1.0f, 0.5f,
    0.0f, 0.5f,
    0.0f, -0.5f,
    1.0f, -0.5f
};
            
// attribute属性を登録
glVertexAttribPointer(positionLocation, 2, GL_FLOAT, false, 0, vertex_position);
glVertexAttribPointer(uvLocation, 2, GL_FLOAT, false, 0, vertex_uv);
            
// モデルの描画
glBindTexture(GL_TEXTURE_2D, waterTexID);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

まとめ

今回は複数枚のテクスチャ表示を行いました。
これでようやくゲームが作れそう・・・と思いきや、まだ行列の話をしていませんでした。
次回は行列を使ったアスペクト比の修正を紹介します。

【Unity】Timelineエディタでムービーを作ってみた

現在時点(2017/3/7)ではTimelineエディタは公式にリリースされているわけではありません。Unity5.6のβ版にマージする感じでビルドされたものが公開されているので、それをダウンロードしてきて使います。

こちらからダウンロードしてください
http://beta.unity3d.com/download/d6790b8476db/public_download.html

また、詳しい情報はこちらに書かれています。
Timeline - Manual

TimeLineエディタはタイムライン上にアニメーションファイルやオーディオファイルを時系列に配置することで、そのシーケンスに従ってアニメーションを実行できるシーケンスエディタです。

f:id:nn_hokuson:20170307192935p:plain:w500

ここでは、以前作ったVR花札のショートムービーをTimelineエディタを使って作り直してみました。作成したムービーは次の通りです。

f:id:nn_hokuson:20170307191402g:plain

前提として、シーンビュー上には地球(earth)、月(moon)、イノシシ(inoshishi)、カメラ(Main Camera)、UI(shutter)が配置されていて、それぞれの動きは、各オブジェクトのAnimation Clipで管理しています。

f:id:nn_hokuson:20170307192522p:plain:w550

これらのAnimation ClipをTimelineエディタ上に並べることでショートムービーを作成してみましょう。

Timelineエディタのファイルを作る

まずはTimelineファイルを作成します。メニューバーから「Assets」→「Create」→「Timeline」→「Timeline」を選択すると、Timelineエディタのファイルが作成されます。

f:id:nn_hokuson:20170307193033p:plain:w400

作成したTimelineファイルを動かすためには、Playable Directorコンポーネントが必要になります。そこで空のゲームオブジェクトを作り、作成したオブジェクトにPlayable Directorコンポーネントをアタッチします。

Playableの欄には先ほど作成したTimelineファイルをプロジェクトビューからドラッグ&ドロップして設定してください。

f:id:nn_hokuson:20170307190621g:plain

さてこれでTimelineエディタを使う準備が整いました。

Timelineのシーケンスを作る

プロジェクトビューに作成したTimelineファイルをダブルクリックして開きましょう。開いたTimelineエディタに地球を回転させるAnimation Clipをドラッグ&ドロップします。

次に、このAnimation Clipを再生するオブジェクトを指定する必要があります。ヒエラルキービューからearthを選択し、Timelineエディタの欄にドラッグ&ドロップしてください。(ヒエラルキービュで>Playable Directorコンポーネントをアタッチしたオブジェクトを選択していないと項目が表示されません)

f:id:nn_hokuson:20170307192022g:plain

これで、地球が回転するアニメーションが再生できるようになりました。実行してみてください。

f:id:nn_hokuson:20170307192259g:plain

同様の手順で、それぞれのAnimation ClipをTimelineエディタにドラッグ&ドロップします。忘れずに各Animation Clipを動かすオブジェクトも設定してくださいね。完成したTimelineエディタは次の通りです。

f:id:nn_hokuson:20170307192935p:plain:w500

まずはイノシシのAnimation Clipを再生し、それにオーバーラップする形で、カメラのAnimation Clipを再生、これにより空が夕焼けっぽくなります。続けて、月を登らせるAnimation Clipを再生し、最後にUIフレームを狭めるアニメーションを再生します。

これを実行すると、Timelineエディタ上で指定した順番でアニメーションが実行され、次のような実行結果になりました。

f:id:nn_hokuson:20170307191402g:plain

まとめ

今回はUnity5.6のベータ版に実装されているTimelineエディタを使ってショートムービーを作ってみました。思っていたよりも簡単にアニメーションのシーケンスを操作できて、おぉってなりました(笑)リリースが待ち遠しいですねー

テラシュールブログさんの記事で、Timelineエディタが公開されていることを知りました〜。いつもお世話になっています^^
tsubakit1.hateblo.jp