LoginSignup
2
2

More than 5 years have passed since last update.

Live2Dでjson読み込みをMechanismで制御する

Posted at

Live2DをMechanismで制御のやり方は中の人が記事に()していますが
moc読み込みが基礎のやり方だったのでjsonを読み込むSampleApp1を基礎にする方法を書いていきます

Mechanismとmodel.jsonファイル

MechanismはUnityのアニメーションサポートの機能で
状態遷移とパラメーターの制御を提供してくれます

mechanism.PNG

moc読み込みの方法ではMechanismの機能でパラメーターをひも付けする形で制御しますが
別個でテクスチャーを用意したり、物理演算をつけたりしなくてはいけません
Live2DViewerで作れるmodel.jsonを読み込む方式では
テクスチャーや表示の切り替え、物理演算や音声が指定した状態のモーションの読み込みまで
全部一発でやってくれます
便利ですね

SampleApp1ではモーションの再生をmodel.jsonに登録されたグループ名を使って
StartMotionとStartRandomMotionで再生させるのですが
これのMechanism側との同機をさせます

必要な機能とその手段

状態遷移とモーションを同機させるのですが
まず遷移が移った時にモーションを開始する機能が要ります
そして終了サイドの動きで
・モーションが終わった時に次の状態へ遷移する機能
・モーションが終わった時にもう一度モーションを再生する機能(アイドリング系向け)
このふたつが必要ですね
表記も必要です
また状態と再生するときのグループ名との対応の機能も必要です

切り替え系に関してはUpdateを監視するのも手なのですが便利な機能があります
animatorでノードを指定してAdd behaviourを押すとスクリプトを追加することができます

StateMachineBehaviourから継承されるこのスクリプトでは
状態のEnter,Update,Exitのタイミングでメッセージ関数を実行してくれます

testBehaviour
using UnityEngine;
using System.Collections;

public class test : StateMachineBehaviour {

    public bool looping;

    override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
        var proxy = animator.GetComponent<LAppModelProxy>();

        if(proxy)
        {
            proxy.GetModel().StartRandomMotion(getcode(animator,layerIndex), LAppDefine.PRIORITY_FORCE);
            animator.SetBool("nomtion",false);
        }
    }

    override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
        var proxy = animator.GetComponent<LAppModelProxy>();

        if (proxy)
        {
            if (proxy.GetModel().getMainMotionManager().isFinished())
            {
                if(looping)
                {
                    proxy.GetModel().StartRandomMotion(getcode(animator,layerIndex), LAppDefine.PRIORITY_IDLE);
                }
                else
                {
                    animator.SetBool("nomtion",true);
                }
            }
        }
    }

    private string getcode(Animator animator, int layerIndex)
    {
        var clips = animator.GetNextAnimatorClipInfo(layerIndex);
        if (clips.Length == 0)
        {
            clips = animator.GetCurrentAnimatorClipInfo(layerIndex);
        }
        return clips[0].clip.name;
    }
}

publicのLoopingはUnityのオブジェクトの方から指定できるようになるので
これでアイドリングするかどうか表記します
モーション再生につかうグループ名はMotionのファイル名を呼び出して使います
機能的に重複した状態もあるので
”次ファイル名、参照できなければ現在ファイル名”をgetcodeで参照できるようにしてあります
link.PNG
(右側はLive2DViewer、2つが対応する形)

このスクリプトを全部のノードに貼り付けます
またアイドリング系のノードにはloopingにチェックを入れておきましょう

Mechanism側の設定

スクリプトを眺めるとanimator.SetBool("nomotion",~~);というところがありますね
モーションの終了判定をMechanism側に伝えるトコロです
前後してしまいますがAnimatorの左側、Parametersの欄でboolで追加します
nomotion.PNG

そうしてから終了時遷移ノード間の矢印の条件設定にnomtionがtrueになったとき動作するように設定します
linksetting.PNG

他のノードは他にパラメーターを用意して通常に条件設定を行います

総評として

Mechanismとパラメーターを連動させるのはMechanism側の機能をフルで使えるので
いろんなことができるようになるでしょう
モデルに無いパラメーターを扱えるのもその一つかもしれません
しかしmodel.jsonと共存させた場合はモデルのパラメーター設計が違うものに対しても
コードを打たずに対応できる強みがありますね
また一つのノードで複数のモーションをランダムに動かすという芸当もできます
あと音声がいっしょに登録できるのも強みかな

グループ名の指定にmotionファイル名を使っていましたが
スクリプトのPublicで指定する方法でもよかったかもしれません

最後にUpdateのなかでなんとかやりくりしようとてた残骸をサンプルに残しておきます

update
        string newcode = parent.ani.GetCurrentAnimatorClipInfo(0)[0].clip.name;
        if (oldcode != newcode)
        {
            StartRandomMotion(newcode, LAppDefine.PRIORITY_FORCE);
            parent.e_nomotion = false;
            oldcode = newcode;
        }
        else
        {

            // 待機モーション判定
            if (mainMotionManager.isFinished())
            {
                // モーションの再生がない場合、待機モーションの中からランダムで再生する
                if (newcode.IndexOf("idle") != -1)
                { 
                    StartRandomMotion(newcode, LAppDefine.PRIORITY_IDLE);
                }
                parent.e_nomotion = true;

            }
            else
            {
                parent.e_nomotion = false;
            }
        }

動作としては同じ内容です

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2