simplestarの技術ブログ

目的を書いて、思想と試行、結果と考察、そして具体的な手段を記録します。

Unity:mecanimのイロハ

SD Toon シェーダーの Unityちゃんで、ステート遷移によってアニメーションが変化する仕組み mecanim を勉強してみようと思います。
ほんとに今更ですが、基本的なところを触ってみます。

f:id:simplestar_tech:20170205134929j:plain

ボーンの入ったモデルと、そのボーンを動かすアニメーションクリップを用意します。
具体的にはモーションを設定した FBX ファイルをどこからか持ってくるという作業です。

今回は SD Toon Unity ちゃんとしました。
入手場所はこちら
unity-chan.com

手順をわかりやすく、まっさらなシーンに Unity ちゃんのモデルを配置してみます。

f:id:simplestar_tech:20170205135922j:plain

メッシュにはディフォルトのマテリアルが割り当てられているので Toon フォルダにある body 用、face 用 hair 用などをそれぞれのメッシュに割り当てます。
加えて、ディレクショナルライトを3つつくり、それぞれ別のレイヤーだけに影を落とすようにし
body, face, hair, head のレイヤーを変更し
Lighting にて Ambient を Skybox から Color White に設定します。
するとこんな見た目に変化します。

f:id:simplestar_tech:20170205142140j:plain

Model をそのまま配置しただけですが、ディフォルトで Animator と Avatar まで割り当たっていました。
これは便利なのでそのまま使いましょう。

次に AnimatorController を作ります。

最初はブレンドツリーというステートを一つ作ってみます。
このステートをダブルクリックすると、次のようなブレンドに関するUIが出てきます。(すでに別途 Walk と Run のモーションをブレンドするように追加した状態です。最初は何もないよ)

f:id:simplestar_tech:20170205145425j:plain

Blend パラメータを調整すれば、二つのモーションをその割合でブレンドするようになります。
そのほかのパラメータ設定は調整次第ですね。ここまで基本的なことができれば、モーションブレンドの基本は OK だと思います。

次に、アニメーションイベントをやってみます。

アニメーションクリップを見てみると、Walk に関しては次のようにアニメーションイベントが設定されています。

f:id:simplestar_tech:20170205150200j:plain

Animator が設定されている階層に、スクリプトコンポーネントを配置して、ここにある Function 名の関数を用意してみます。
すると、アニメーションが開始されたタイミングでこの関数が呼ばれます。

要は、モーションのあるタイミングで表情や音、エフェクトなどを発生させたいときなどに、これらのイベントをモーションに仕込んでおくと便利なことになりそうです。
何処にイベントを仕込んだのか、一覧表示できるとうれしいですが、そういうところ気が利かない機能かもしれません。(どこからも呼ばれないはずの関数が呼ばれてしまうというバグが残りそう…)

public class UnityChanBehaviour : MonoBehaviour {
    public AnimationClip[] animations;
    // Use this for initialization
    void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		
	}

    public void OnCallChangeFace(string str)
    {
        int ichecked = 0;
        foreach (var animation in animations)
        {
            if (str == animation.name)
            {
                ChangeFace(str);
                break;
            }
            else if (ichecked <= animations.Length)
            {
                ichecked++;
            }
            else
            {
                //str指定が間違っている時にはデフォルトで
                str = "default@unitychan";
                ChangeFace(str);
            }
        }
    }

    void ChangeFace(string str)
    {
        //isKeepFace = true;
        //current = 1;
        //anim.CrossFade(str, 0);
    }
}

次に基本的な機能の、ブレンドマスクを見てみます。
例えば、先ほどのアニメーションイベントにて呼ばれた関数で、顔の表情だけを別のアニメーションにしてみたいと思います。

ブレンドマスクにはこんな感じで、faceだけ適用する旨を設定します。
f:id:simplestar_tech:20170205153913j:plain
あとは Face という、もう一つのレイヤーを AnimationController に追加して、そこに表情のステートを追加します。遷移をいちいち書かないのがポイント。
f:id:simplestar_tech:20170205154006j:plain

アニメーションイベントで呼ばれる関数にて、CrossFade 関数を呼べば、遷移をかかずとも、そのステートに遷移します。

    public void OnCallChangeFace(string str)
    {
        int ichecked = 0;
        foreach (var animation in animations)
        {
            if (str == animation.name)
            {
                ChangeFace(str);
                break;
            }
            else if (ichecked <= animations.Length)
            {
                ichecked++;
            }
            else
            {
                //str指定が間違っている時にはデフォルトで
                str = "default@unitychan";
                ChangeFace(str);
            }
        }
    }

    void ChangeFace(string str)
    {
        anim.CrossFade(str, 0.4f);
    }

歩いているときに飛んでくるアニメーションイベントでスマイルし
f:id:simplestar_tech:20170205154159j:plain

走っているときに飛んでくるアニメーションイベントで驚きます。
f:id:simplestar_tech:20170205154242j:plain

gif アニメをとるとこんなイメージです。

f:id:simplestar_tech:20170205155112g:plain

mecanimの基本的な機能はこんなところでしょうか。
もっと便利な機能を見つけましたら、またどこかで書こうと思います。

ユニティちゃんライセンス

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