サークル獏の佐藤敏 Unityとか備忘録

サークル獏の佐藤敏がUnityとかで知ったTipsを書いておく備忘録です。

Unity(のHumanoid)でクソみたいなAnimationControllerをできるだけ使わずにやる

Unityで3DキャラをアニメさせるとなるとまずはAnimationControllerのノードをいじってヒーコラってことになるんでしょうが、端的に言ってクソです。
UIデザイナーさんがUIをアニメーションさせるくらいならいいとして、3Dアニメーションでノードの線をアレコレ伸ばしてまともに使う気になれません。

そんなわけでPlayable APIを使っていきましょう。
ぜんぶ自力でもいけるんでしょうけど、今や便利なライブラリがあるのでそれを使わせていただきます。
gologius.hatenadiary.com
 
 

準備1(主にダウンロード編)

まず新規で3Dのプロジェクトを作り、

assetstore.unity.com
我らがTaichi Character Pack君に登場してもらいます。
 
 
キャラとしてもデキが良くてHumanoid形式のanimもたくさん入っているいいアセットです。けっこう重いですが、Unity アセットストアからダウンロードしてインポート。
(VRoidとかを使うとしても基本は変わりません。VRM importerとかを入れる必要は出てきますが)


つづいてMotion Playerをダウンロードします。こちらにアクセスして「Clone or Download」→「Download Zip」でzipをダウンロード。
github.com

f:id:VinSatoo:20191204003155p:plain
解凍して、Unityのプロジェクトフォルダに放り込みましょう。

f:id:VinSatoo:20191203200726p:plain
こんなんなりました。MotionPlayerについては別のフォルダを作ったほうが良かったかもしれないですな。
 
 

準備2(主にキャラ配置編)

f:id:VinSatoo:20191203201830p:plain
「TaichiCharacterPack」→「Resources」→「Taichi」→「Models Mecanim」フォルダからとりあえず「m01_jersey_00_l」を選び、

f:id:VinSatoo:20191203201135p:plain
Scene画面にドラッグ&ドロップして、

f:id:VinSatoo:20191203201242p:plain
ひとまずPositionとかは全部0にします。

f:id:VinSatoo:20191203201947p:plain
後ろを向かれているとさみしいのでMain Cameraの位置と回転と「Field Of View」についてはこんな数字にしましょうか。

ちなみに「Field Of View」は結構キャラの印象が変わるので注意しましょう。キャラがでかすぎる・小さすぎるというときも、カメラ自体を動かすか、FoVを変えるかでだいぶ見た目は変わります。
udasankoubou.blogspot.com
 
 

準備3(いやなAnimation Controller編)

Animation Contollerはイヤですが、多分これを設定しないと色々不便です。
形式だけ、設定しましょう。

f:id:VinSatoo:20191203202922p:plain
「MyAssets」→「controller」というフォルダを作りました。そこの中で右クリックして、「Create」→「Animation Controller」を選びましょう。
とりあえず「taichi_controller」という名前にしました。

f:id:VinSatoo:20191203203456p:plain
んで、Hierarchyから「m01_jersey_00_l」を選んで、Taichiにさっき作ったカラッポのAnimation Controllerを設定してあげます。
 

ほんで普通?のやり方に寄り道

f:id:VinSatoo:20191203203655p:plain
「Animator」タブを選んで、

f:id:VinSatoo:20191203203817p:plain
Taichiくんのアセットから「m01@back_20」の左の矢印をクリック、出てきた「back_20」を……

f:id:VinSatoo:20191203203943p:plain
Animatorタブにドラッグ&ドロップするとこうなりますんで、

f:id:VinSatoo:20191203204047p:plain
Unityのプレイボタンを押すと無限にバックするTaichi君が誕生。その上でAnimation Controllerを色々細かくいじっていくのが普通???のやり方ですね。
 
 

だがそれはクソだ。でもまだ準備は続く……

f:id:VinSatoo:20191203204336p:plain
先ほどと同じように、今度は「m01@idle_00」の左の矢印をクリック、「idle_00」をクリックして……

f:id:VinSatoo:20191203204459p:plain
Ctrlキーを押しながらDキーを押します。「複製」という意味です。
するとanimファイルだけ抜き出せます。

f:id:VinSatoo:20191203205232p:plain
同じことを繰り返して、他に「idle_20」「jump_10」「kick_20」というanimファイルを抜き出しました。

f:id:VinSatoo:20191203205520p:plain
んで「Resources」「anim」という名前のフォルダを作って、4つのanimファイルを移動させます。
※重要! ここで「Resources」はスペルミスすると動かないので慎重に。
 
 

ひとまずMotionPlayerをつけてあげる

f:id:VinSatoo:20191203210418p:plain
Taichi君(m01_jersey_00_l)に、Motion Playerをつけてあげます。
Add Componentを押して、Motionとか打ってあげれば「Motion Player」が出てくるはず。
出てこない場合は、「準備1」のMotion Playerを入れるどっかでミスっていると思います……

f:id:VinSatoo:20191203210548p:plain
こんな感じになったかと思います。
 
 

maskの作成

f:id:VinSatoo:20191203211411p:plain
つづけて、「MyAssets」フォルダに「mask」フォルダを作って「Create Avater Mask」とします。mymaskなど適当な名前をつけて保存。

f:id:VinSatoo:20191203211959p:plain
この「mymask」をプロジェクトからクリックして「Humanoid」を開くと最初は全部が緑になっていますが、腕・手先だけ緑で残し、他はクリックして赤にしてしまいましょう。

f:id:VinSatoo:20191203211705p:plain
で、Taichi君のMotionPlayerの「upper Mask」にさっき作ったmymaskを指定しておきましょう。
 
f:id:VinSatoo:20191203215401p:plain
mymaskが設定できました。
 
  

プログラマーっぽくなってくるよ

f:id:VinSatoo:20191203205718p:plain
「Game Object」→「Create Empty」でカラのオブジェクトを作り、名前を「GameObject」から「GameManager」に。

f:id:VinSatoo:20191203205957p:plain
「Create And Add」を押すと、ビミョーにタイムラグがあって、

f:id:VinSatoo:20191203210154p:plain
こんな風にGameManagerコンポーネントが付けられます。まだカラッポなので、歯車アイコンをクリック、Edit Scriptで中身を書いてあげましょう。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour
{
	// Start is called before the first frame update
	MotionPlayer motionPlayer;
	GameObject taichi;

	float tick; //時間記録

	AnimationClip[] clipAr; //読み込んだanimの配列
	
    void Start()
    {
		taichi = GameObject.Find("m01_jersey_00_l"); //Taichiを探す
		if (taichi == null) {
			Debug.Log("Taichi が見つかりません。");
		} else {
			motionPlayer = taichi.GetComponent<MotionPlayer>(); //MotionPlayer保存

			clipAr = Resources.LoadAll<AnimationClip>("anim"); //アニメ読み込み
		}
	}

    // Update is called once per frame
    void Update()
    {
		if (taichi != null) {
			tick += Time.deltaTime;
			if (tick >= 1.0f) { //1秒ごとに
				tick -= 1.0f;
				var newAnim = clipAr[UnityEngine.Random.Range(0, clipAr.Length)]; //ランダムにアニメ選ぶ
				motionPlayer.play(newAnim, 0, true);
				Debug.Log(newAnim); //何を表示しているかデバッグ画面に表示
			}
		}
    }
}

こんな感じでいいと思います。
 
 

実行してみると?

Taichi君が1秒ごとに4つのモーションをランダムに動かします。
ここまでの作業で分かったとおり、Animation Controllerに手動で登録することはしていません。
形式的に登録した「back_20」を削除してもちゃんと動きます(実行直後だけおかしくなりますが)。

もちろんif (tick >= 1.0f)  を if( Input.GetKeyDown(KeyCode.Space)) とかに書き換えれば1秒ごとではなくスペースキーを押すたびにモーションが切り替わります。Animation Controllerの面倒なノード設定からはこれでオサラバ!? です。
 
 

さらにMotionPlayerの魅力はここから

GameManagerスクリプト

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour
{
	// Start is called before the first frame update
	MotionPlayer motionPlayer;
	GameObject taichi;

	float tick; //時間記録

	AnimationClip[] clipAr; //読み込んだanimの配列
	
    void Start()
    {
		taichi = GameObject.Find("m01_jersey_00_l"); //Taichiを探す
		if (taichi == null) {
			Debug.Log("Taichi が見つかりません。");
		} else {
			motionPlayer = taichi.GetComponent<MotionPlayer>(); //MotionPlayer保存

			clipAr = Resources.LoadAll<AnimationClip>("anim"); //アニメ読み込み
			motionPlayer.play(clipAr[0], 0, true); //修正
		}
	}

    // Update is called once per frame
    void Update()
    {
		if (taichi != null) {
			tick += Time.deltaTime;
			if (tick >= 1.0f) { //1秒ごとに
				tick -= 1.0f;
				var newAnim = clipAr[UnityEngine.Random.Range(0, clipAr.Length)]; //ランダムにアニメ選ぶ
				motionPlayer.play(newAnim, 1, true); //修正 上半身の動き
				Debug.Log(newAnim); //何を表示しているかデバッグ画面に表示
			}
		}
    }
}

こんな風にしてみましょう。

f:id:VinSatoo:20191203214438p:plain
Taichi君が上半身だけの謎ダンスを始めたはずです。
これがMotionPlayerの魅力で、上半身と下半身で別の動きをさせることができます(avater maskの設定によってはさらに色々な動きもできますが、腕だけmaskするのが一番効果的だと思います)。
 
特に「上半身の動きが派手すぎる」「下半身の動きが派手すぎる」市販のモーションをうまく活用するのに使えるでしょう。

<<