Qiitaには画像のアップロード容量上限があるようなので、古い記事を全て再構成して圧縮を計っている。
こんな便利なやつがある
これは ジャンプキック したときの動きだ。
ジャンプした、キックした、といった流れが リアルタイムに見れる。開発中に動きがおかしくなったときの調査で役に立つ。
それは何なの?
この グラフみたいなやつが アニメーター。 別に、アニメ以外のことにでも使える。
どこにあるの?
アニメーション・クリップを作るときに、アニメーターが オマケに1個 作られる。
Unityのアニメーター・コントローラーを使ってモーションの状態遷移をC#スクリプトで組もうぜ
空中で歩いてしまっているときがある。
手作業で モーションとモーションをつなげていると、ミスというのはある。
じゃあ直そう。こういうとき、Unityのアニメーター・コントローラーが使える。
公式の記事はこれ。
「AnimatorController」unity DOCUMENT
https://docs.unity3d.com/ja/current/ScriptReference/Animations.AnimatorController.html
まず各部名称
ここは読み飛ばして、あとで読み返してもいい。
ユニティー・エディターと、ユニティー・エンジン
普段、これ(上図、黄色の円)で開発していると思うが、これが ユニティ・エディター(UnityEditor)。
ゲーム・ビュー(上図、赤色の円)でゲームを動かしているのが ユニティー・エンジン(UnityEngine) だ。
C#スクリプトを書くとき、
using UnityEditor;
using UnityEngine;
と冒頭に書くことがあるだろう。
ゲームとしてリリースするときは、 using UnityEditor; を使っているコードは製品に含めないだろう。
using UnityEditor; を使うときは、特別ルールが1つあって、あとで説明する。
##レイヤー
これ、レイヤーの一覧。 上図では [Base Layer] の1つしか使っていない。
##ステートマシン
これ、ステートマシン。線が引っ張ったりしているやつだ。
日本語で言うと 状態遷移図。
この六角形には、さらに ステートマシン が入っている。
ステートマシンというのは 親子の入れ子構造にできる。
###ステートのプロパティ
微妙に GUIで表示されているものと、C#スクリプトでのプロパティー名は異なる
##トランジション
ステート と ステート をつないでいるのが、トランジション(白い矢印)だ。
ステートマシン(六角形)のやつ ともくっつく。
###トランジションのプロパティ
微妙に GUIで表示されているものと、C#スクリプトでのプロパティー名は異なる
##コンディション
トランジションは、コンディションを持っている。[Inspector]で見れるやつだ。
ツリー構造になっている
主要なのが6つ。
(1) Layer
(2) StateMachine
(3) State ※ステートマシンの入れ子の葉っぱに当たる
(4) Transition ※StateとStateを結んでいる線。 StateMachineともつながる。
(5) Condition
(6) Position
実装を見ると チャイルドなんとか という入れ物にラッピングされるように ステートマシンが入っているが、基本的にステートマシン上の位置(座標とか)を入れているラッパーで包んでいるだけだ。ツリー構造に変わりはない。
アニメーターは C#スクリプトで作ろう
今はまだ プログラムの書き方を説明していないが、これらの部品は C#スクリプトから作ることができる。
多くの部品は読み取り専用だが、新規作成/追加/削除 を利用して 取っ換えることができる。
部品によっては 全部廃棄して新規から同じものを作り直す 全取っ替え をしなければいけないものもある。
GUIを使って手で線を引っ張っていると 数が多くて つらいので、C#スクリプトから作れるようになっていこう。
じゃあ、このアニメーターは何のためのGUIかというと、リアルタイムに状態遷移を確認、不具合調査をするための監視ウィンドウぐらいに思っておこう。
using UnityEditor; の使い方
using UnityEditor; を使うときは、特別ルールが1つある。
Assestフォルダーの下にどこでもいいので Editor
フォルダーを作って、その下に using UnityEditor; を使う C#スクリプトを入れることだ。
Editor フォルダーは何個作ってもいい。
他に関連する特別なフォルダー名としては Editor Default Resources
も使うことがあるかもしれない。
「特殊なフォルダー名」unity DOCUMENTATION
https://docs.unity3d.com/jp/current/Manual/SpecialFolders.html
使ってみる
Editor フォルダーを右クリックして、[Create] - [C# Script] を選び、いいかげんな名前 Banana1 というスクリプトをとりあえず作るとする。
上図左下を見てほしい。
いつもは Assembly-CSharp プロジェクトの下に C# スクリプトを書いていたと思うんだが、ユニティー・エディター用の C#スクリプトは Assembly-CSharp-Editor プロジェクトの下に自動的に分別される。
Banana1.cs には次のように書く。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor; // 追加
public class Banana1 : MonoBehaviour {
[MenuItem("Bye bye Earth!/Rocket1/Space2/Moon3")]
static void GoToTheMoon()
{
Debug.Log("Moon is great!");
}
}
Unityで知っておきたい基本操作は別記事にまとめた:http://qiita.com/muzudho1/items/8fa08d0d2b4c205df49c
#じゃあ、UNITY公式のサンプル・プログラムを実行してみよう。
(再掲)
https://docs.unity3d.com/ja/current/ScriptReference/Animations.AnimatorController.html
###Mecanim フォルダーを作る。
まず、Assets フォルダーの下に Mecanim というフォルダーを作る。
Mecanim という名前のフォルダーに意味はない。サンプルでの練習が終わったら消してもいい。
###コードをいじろう
一度に実行すると 変化についていけないので、コメントアウトしながら 少しずつ実行していく。
サンプル・プログラムは 変数名や コメント等を 改造してしまった。
// (1)サンプルのコントローラー(ファイル)を見に行く☆
var controller = UnityEditor.Animations.AnimatorController.CreateAnimatorControllerAtPath("Assets/Mecanim/StateMachineTransitions.controller");
// (2)アニメーター・ビューの[parameters] に C#スクリプトから 4つ追加する。
controller.AddParameter("TransitionNow", AnimatorControllerParameterType.Trigger);
controller.AddParameter("Reset", AnimatorControllerParameterType.Trigger);
controller.AddParameter("GotoB1", AnimatorControllerParameterType.Trigger);
controller.AddParameter("GotoC", AnimatorControllerParameterType.Trigger);
// (3)ステートマシン(六角形のやつ)を3つ追加する。
var rootStateMachine = controller.layers[0].stateMachine;
var smA = rootStateMachine.AddStateMachine("smA"); // stateMachineA
var smB = rootStateMachine.AddStateMachine("smB"); // stateMachineB
var smC = smB.AddStateMachine("smC"); // stateMachineC
この C#スクリプトを さっきのように Editor フォルダーの下に入れ、[MyMenu] - [Create Controller] から実行すると、
Assets/Mecanim フォルダーの下に StateMachineTransitions.controller (アニメーター・コントローラー)ファイルが作られ ……(1)
画面左端の方には TransitionNow、Reset、といったトリガーが並び、……(2)
そのとなりの方眼紙のところには smA、smB といった六角形の箱(これをステートマシンと呼ぶ)ができている。なお、smC は smB の中に入っている。……(3)
[Entry] [Any State] [Exit] は どこにでも入っている。
[(Up) Base Layer] は、上に戻るぐらいの意味だ。
// (4)ステート(長方形のやつ)を5つ追加する。
var stateA1 = smA.AddState("stateA1"); // (5)(6)
var stateB1 = smB.AddState("stateB1"); // (7)
var stateB2 = smB.AddState("stateB2"); // (7)
smC.AddState("stateC1"); // (8)
var stateC2 = smC.AddState("stateC2"); // (8) don’t add an entry transition, should entry to state by default
ステート(長方形)を追加する。あとで線を引っ張るものは、var を使って 変数に取り置きしている。
(5)
最初に作ったのが stateA1 なので、smA の方に 暗いオレンジ色の矢印が伸びているようだ。
(6)
左上のパンくずリストに書いてあるとおり、smA の中に stateA1 ができている。また、1つ上の階層の Base Layer の Entry から伸びてきた線が、Entry から入ってきて stateA1 につながっている。
オレンジ色の線は、最初に実行されるステートにつながっている。明示的に設定していないときは暗い色の線になっている。
(7)
smB の中もにぎやかだ。 stateB1、stateB2 が新しく作られている。 smC は その前の(3)で作ったものだ。
ここでは Entry から stateB1 につながっている。
(8)
smC の中には stateC1 と stateC2 が作られている。
#白い矢印の線(トランジション)を付けよう
よく分からないコードもある。
// 以下、トランジション(白い矢印の線)を追加する。
// (5)stateA1 から Exit へのトランジション
var exitTransition = stateA1.AddExitTransition(); // stateA1 は Exit につなげる。
exitTransition.AddCondition(UnityEditor.Animations.AnimatorConditionMode.If, 0, "TransitionNow"); // 条件にトリガーを追加する
exitTransition.duration = 0; // duration は 0 に。
// (6)(これは分からない) stateA1 と Any State がつながっていないようだが?
var resetTransition = smA.AddAnyStateTransition(stateA1);
resetTransition.AddCondition(UnityEditor.Animations.AnimatorConditionMode.If, 0, "Reset");
resetTransition.duration = 0;
stageA1 が Exit につながったのは分かるんだが ……(5)
別に smA の Any State も、上の階層の Any State も、stateA1 にはつながっていない。……(6)?
C#スクリプトで Any State から線を引く方法はあるんだが、ひとまず公式のサンプル通り 先に進もう。
// (7)stateB1 は Entry につなげる。
var transitionB1 = smB.AddEntryTransition(stateB1);
transitionB1.AddCondition(UnityEditor.Animations.AnimatorConditionMode.If, 0, "GotoB1"); // 条件にトリガーを追加する。
// (8)stateB2 も Entry につなげる。
smB.AddEntryTransition(stateB2);
// (9)stateC2 は Entry につなげる方法ではなく、デフォルトとして設定する。
smC.defaultState = stateC2;
// (10)stateC2 は Exit につなげる。
var exitTransitionC2 = stateC2.AddExitTransition();
exitTransitionC2.AddCondition(UnityEditor.Animations.AnimatorConditionMode.If, 0, "TransitionNow"); // 条件にトリガーを追加する。
exitTransitionC2.duration = 0;
線(トランジション)をクリックして Inspector ビューを見ると
Conditions に GotoB1 トリガーが設定されていることが分かる。……(7)
また、smC に線が伸びているが、これは stateC2 がデフォルト設定になっているので、そこへ伸びていっているものだ。
上の階層から Entry を経由して stateC2 に線がつながっている。
#ステートマシン(六角形)同士をつなげよう
ステートを直接つなぐ以外にも、ステートマシンをつなぐ方法がある。
この場合、遷移元のステートマシンの Exit と、遷移先のステートマシンの Enter がつながる。
一部 はしょったが、サンプル・プログラムは ここまでだ。
これで 線をつなげるのは C#スクリプトから できることが分かった。
予備知識
Project
|
+-- ゲームオブジェクト
~~~~~~~~~~~~~~~~
|
+-- スプライト・レンダラー
|
+-- アニメーター
ゲーム画面上に置いてあるものを ゲームオブジェクト と呼ぶ。
画像(≒スプライト)を貼り付けたり、モーション遷移(≒アニメーター)を付けたりする。
Project
|
+-- ゲームオブジェクト
|
+-- スプライト・レンダラー
|
+-- アニメーター
Assets/Resources/Sprites
|
+-- スプライト
~~~~~~~~~
ゲームオブジェクトとは別にスプライトがあるわけだが、このスプライトは単に画像ぐらいと思っておけばいい
Project
|
+-- ゲームオブジェクト
|
+-- スプライト・レンダラー
|
+-- アニメーター
Assets/Resources/Sprites ※別にこのフォルダーでなくてもいい
|
+-- スプライト
|
+-- タイル状にスライスした画像の1枚1枚
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
スプライトは、スプライト・エディターを使って 1枚の画像を タイル状にスライスしたことを覚えておくこともできる。
Project
|
+-- ゲームオブジェクト
|
+-- スプライト・レンダラー
| ~~~~~~~~~~~~~~~~~~~~
|
+-- アニメーター
Assets/Resources/Sprites ※別にこのフォルダーでなくてもいい
|
+-- スプライト
|
+-- タイル状にスライスした画像の1枚1枚
スプライト・レンダラーは、スプライトを描画するものだ。
Project
|
+-- ゲームオブジェクト
|
+-- スプライト・レンダラー
| |
| +-- スプライト
| ~~~~~~~~~
|
+-- アニメーター
Assets/Resources/Sprites
|
+-- スプライト
~~~~~~~~~
|
+-- タイル状にスライスした画像の1枚1枚
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
スプライト・レンダラーに スプライトを指定すれば、
タイル状にスライスした画像を参照できるようになり、
アニメーションの高速描画を担当させることができる。
Project
|
+-- ゲームオブジェクト
|
+-- スプライト・レンダラー
|
+-- アニメーター
Assets/Resources/AnimationClips ※別にこのフォルダーでなくてもいい
|
+-- アニメーション
~~~~~~~~~~~~~
Assets/Resources/Sprites
|
+-- スプライト
|
+-- タイル状にスライスした画像の1枚1枚
どのような アニメーションにするかは、アニメーション というファイル に覚えさせる。
ドープシート(≒タイムライン)に スライスした画像を並べてモーション・アニメーションを作ることができる。
Project
|
+-- ゲームオブジェクト
|
+-- スプライト・レンダラー
| |
| +-- タイル状にスライスした画像の1枚1枚
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
+-- アニメーター
Assets/Resources/AnimationClipsい
|
+-- アニメーション
|
+-- タイル状にスライスした画像の1枚1枚
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Assets/Resources/Sprites
|
+-- スプライト
|
+-- タイル状にスライスした画像の1枚1枚
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ここらへん全部、スライスした画像を間にして 依存しあいあっているわけだ。
次の記事に続く。
「Unityのアニメーター・コントローラーはどこまでC#スクリプトで作成できるかやってみた」
http://qiita.com/muzudho1/items/f6d8a10d057307057b7f
「Unityで状態遷移を組むときに使うアニメーター・コントローラーを作成するC#スクリプトのソースコード」
http://qiita.com/muzudho1/items/d2a76d79b8a6b8437897