Live2DモーションをStateMachineBehaviours制御

前に書いた[Live2DのモーションをMecanim制御する](http://qiita.com/naotaro0123/items/f32e9655f78c91b27a0f)ですが、ちょっとバグってました。
![01.png](https://qiita-image-store.s3.amazonaws.com/0/15028/5b61c2ca-a934-129e-58a7-07d2477d961e.png)


Mecanimのparameter値を変えた瞬間には、次のモーションファイル名が取得できておらず前のモーションファイル名を取得してた...。

この問題ですが、Unity5から追加されたState Machine Behavioursで解決できました。
State Machine Behavioursは、コードからMecanimのState作成できたり、状態遷移タイミングを細かく取得できるものです。

# State Machine Behavioursで制御する手順
今回もLive2D Unity SDKのMotionプロジェクトを使っていきます。
（sample\Motion\Assets\Scene\Sample.unity）

１）Live2DモデルにAnimatorを追加します
![02.png](https://qiita-image-store.s3.amazonaws.com/0/15028/edcda125-a603-2242-9741-53fa80237985.png)

２）[Assets]-[Create]からAnimator Controllerを作成し、アタッチする
![03.png](https://qiita-image-store.s3.amazonaws.com/0/15028/df9cf6e1-dae3-0972-084b-9f977294d5c2.png)

３）HirarchyでLive2DModelを選択した状態で、[Window]-[Animation]を開き[Create New Clip]で新規Animationを2つ作る。
![04.png](https://qiita-image-store.s3.amazonaws.com/0/15028/fcb75ef1-5712-a498-328a-aa4d2bdb0e31.png)

1つはidle.anim、もう1つはmotion1.animとしておく。

４）Add Propertyボタン押下し、Motion Fileの+ボタン押下する
![05.png](https://qiita-image-store.s3.amazonaws.com/0/15028/d37593d9-da52-4460-a12d-08f4f60a57e0.png)

５）1:00のキーフレームはDeleteし、0:00の方を選択し、InspectorのMotion Fileを指定します
![06.png](https://qiita-image-store.s3.amazonaws.com/0/15028/3c0c8ddc-41a4-4926-622d-0c035ce3a39d.png)

![07.png](https://qiita-image-store.s3.amazonaws.com/0/15028/d0ef2ece-3554-e0e3-fc89-858d5141360a.png)

６）もう1つのモーションも同様にする
![08.png](https://qiita-image-store.s3.amazonaws.com/0/15028/fb25f106-ece4-e814-38a1-0deacba84e7b.png)

![09.png](https://qiita-image-store.s3.amazonaws.com/0/15028/8a769e21-cd15-5847-fcf0-875a147c7fb5.png)

７）MakeTransitionでつないでパラメータを作る
![10.png](https://qiita-image-store.s3.amazonaws.com/0/15028/83ed7869-8211-fabc-02fa-a05931c46485.png)

８）Transitionの矢印を選択し、Motion=1の時はmotion1へ、Motion=0の時はidleへ行くようにする
![11.png](https://qiita-image-store.s3.amazonaws.com/0/15028/2daad75d-59e0-6167-28da-183199dc06c4.png)

![12.png](https://qiita-image-store.s3.amazonaws.com/0/15028/641b088e-1d71-050c-cca3-e60042bc7b74.png)

９）AnimatorのBase LayerのInspectorでAdd Behaviourボタン押下し、Scriptを作る
![13.png](https://qiita-image-store.s3.amazonaws.com/0/15028/6c0d0049-c640-36cc-392b-01b6213032ad.png)

１０）SteteMachineソースを以下のようにする

```csharp:MotionBehaviour.cs
using UnityEngine;
using System.Collections;

public class MotionBehaviour : StateMachineBehaviour {

	public bool changeflg = false;   // モーションチェンジフラグ

	// 次のステートに移り変わる直前に実行される
	public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
	{
		changeflg = true;
	}
}
```

１１）メインのソースも以下のように修正する

```csharp:SimpleModel.cs
using UnityEngine;
using System;
using System.IO;
using System.Collections;
using live2d;

[ExecuteInEditMode]
public class SimpleModel: MonoBehaviour 
{
	private Live2DModelUnity live2DModel;
    private Live2DMotion motion;
    private MotionQueueManager motionMgr;

    private Matrix4x4 live2DCanvasPos;

    public TextAsset mocFile ;
    public Texture2D[] textureFiles ;
    public TextAsset motionFile;

	private Animator anim;    // Animator
	private MotionBehaviour mtnBehaviour;    // MotionBehaviour

	void Start () 
	{
        Live2D.init();
		// Animatorを取得
		anim = GetComponent<Animator>();
		// State Machine Behavioursを取得
		mtnBehaviour = anim.GetBehaviour<MotionBehaviour>();

        live2DModel = Live2DModelUnity.loadModel(mocFile.bytes);

        for (int i = 0; i < textureFiles.Length; i++)
        {
            live2DModel.setTexture(i, textureFiles[i]);
        }

        float modelWidth = live2DModel.getCanvasWidth();
        live2DCanvasPos = Matrix4x4.Ortho(0, modelWidth, modelWidth, 0, -50.0f, 50.0f);

        motionMgr = new MotionQueueManager();
        motion = Live2DMotion.loadMotion(motionFile.bytes);
	}
	
	
	void OnRenderObject()
	{
        if (live2DModel == null) return;
        live2DModel.setMatrix(transform.localToWorldMatrix * live2DCanvasPos);

        if ( ! Application.isPlaying)
        {
            live2DModel.update();
            live2DModel.draw();
            return;
        }

		// モーションが終了していたら or フラグが更新されていたら
		if (motionMgr.isFinished() || mtnBehaviour.changeflg == true)
		{
			// モーションのロード
			motion = Live2DMotion.loadMotion(motionFile.bytes);
			// モーションスタート
			motionMgr.startMotion(motion);
			// フラグをOFFにする
			mtnBehaviour.changeflg = false;
		}

        motionMgr.updateParam(live2DModel);
		
		live2DModel.update();
		live2DModel.draw();
	}
}
```

１２）これで瞬時にモーションが切り替わるようになりました！
![motion.gif](https://qiita-image-store.s3.amazonaws.com/0/15028/da04d3c5-d6d1-a8b6-8a35-03421f233d37.gif)

###参考にしたページ
・[Unity Document - State Machine Behaviourとは](http://docs.unity3d.com/ja/current/Manual/StateMachineBehaviours.html)
・[Unity Document - State Machine Behaviour](http://unity3d.com/jp/learn/tutorials/modules/beginner/5-pre-order-beta/state-machine-behaviours)
・[Unity5.0の新しいアニメーション機能](http://japan.unity3d.com/blog/?p=1672)
・[Mecanimを使ってユニティちゃんを動かしてみた、で出た疑問点を解消していく](http://kikikiroku.session.jp/unity5-mecanim-animation-study/)
・[Unity5 MecanimのStateMachineBehaviourと戯れる](http://tsubakit1.hateblo.jp/entry/2015/05/01/032208)