このブログで使用しているUnityのVer
・Unity 2022.3.19f1
こんにちは!個人でゲーム制作をしているちょっと寂しい男、えきふるです!
はじめに
アニメーションの勉強が進んで、プレイヤー側の操作やゲーム中の条件でアニメーションを再生させたいって事ありますよね。
もしくはスクリプト側で指定して条件を満たした場合にアニメーションが再生されたり。
例えばRPGでは「戦う」コマンドが選択されたら攻撃モーションをして欲しいですし、横スクロールアクションで敵に当たったらのけ反って欲しい。アドベンチャーゲームで指定の場所を触ったらリアクションがある…とか。
今回はそんなアニメーションに条件付けをして遷移、再生させる方法をAnimator Controller (アニメーターコントローラー) 内のアニメーションパラメーターという仕組みを使って学んでいきたいと思います。
アニメーターコントローラーはUnityのアニメーションシステム全体の中で下記のような指揮者のような役割でした。
この辺りの基本的な部分に不安がある方は下記を見て見て下さい。
では、ステートの遷移条件をコントロールする事でアニメーションを分岐させる方法を見て行きましょう。
・アニメーションパラメーターの使い方
・Conditions(Transitionパラメーター)の使い方
・変数(Trigger、Bool、Integer、Float)を使ったアニメーションの条件分岐
・アニメーションパラメーターの変数の制御の仕方
アニメーターコントローラーやステートの基本に関して不安な人は下の記事をチェックふる!
アニメーションの条件付けの方法:概要
それでは、AnimatorControllerを使ってアニメーションを条件によって再生させる方法を見ていきましょう。
条件分岐の基本構造
まず、アニメーションの変数を使って条件分岐させる為のUnityの仕組みを見て行きます。
分かり易い様に一枚の絵にしてマトメてみました。
条件分岐では条件をつけたいゲームオブジェクトのアニメーターコントローラーで
①変数を作成して
②それぞれの遷移に変数の中身がどうなったら遷移するかの条件を付ける。
③変数の中身を変えるための外部から制御する仕組み(例えばスクリプトでInt型変数を呼び出してIntに1を代入とか)を組んであげます。
という流れで設定していきます。
じゃあ実際の作業手順を見ていこう〜!
遷移条件の使い方
それでは具体的に手順を見ながら設定方法を確認していきましょう。
1.最初に、アニメーションの遷移状況
最初に現在のアニメーションの設定状況を確認しておきます。
今、ゲームシーンの中にはCubeというオブジェクトが1つあり
Cubeのアニメーションコントローラーでは以下のように各アニメーションがTransitionで繋がっています。
Idleというステートから始まり、Move01に繋がりそこから「Attack01」「Attack02」というアニメーションに派生します。
現状では各遷移に変数による条件分岐は付けていません。
イメージ的にはキャラクターが移動中にボタン入力したらボタンに応じて2パターンの攻撃をする感じです。
各ステートのアニメーションは下記のような感じです。
・idle(待機モーション)
・Move(移動モーション)
・Attack01(攻撃モーション01)
・Attack02(攻撃モーション02)
2.変数の作成
次にTransitionの条件をつけるためのAnimatorContoroller用の変数を作成します。
変数の作成はAnimatorControllerウインドウのParametersタブで任意の変数を選んで作成します。
下記の手順で作成してみましょう。
1,ウインドウはメインメニューの「Window」→「Animation」→「Animator」で開けます(Macの場合ですがWinもさほど変わらないと思います。)
ちなみに「Animator Parameter」で直接変数を作成するParameterだけのウインドウも出せるのですが、この後Transitionやステートを組む事などを考えると「Animator」の方で開く方が断然オススメです。
「Animator」で「Animator Contoroller」ウインドウが開きます。
※「Animator」ウインドウという言い方をすると他の似たアニメーション関連のウインドウや用語と混乱をするのでこんな言い方にしています。
2.Parametersタブで変数を作成します。
もしタブが無いという方は目のマークを押してみてください。ここでタブのON/OFFができます。
それでは、タブ右側の「+」ボタンを押すと作成できる変数の項目が出てくるので、任意のものを選びましょう。
今回はInt型で進めたいと思います。
Int型を選んで「TestInt」という名前をつけて変数を作りました。
ちなみに「+」の左横にある「Name」と書いてある場所は変数を沢山作った時に名前でフィルターをかける検索窓です。
※この時、タブがよく「Layers」になっていて、あれ?変数作れない!なんて事になるので必ずタブが「Parameters」の方になっているか確認してくださいね。…え、そんなミスするの私だけ?
3.Transitionに条件を設定
次に、先ほど作った変数を使ってMove01から分岐するAttack01、Attack02に条件をつけましょう。
Move01→Attack01に伸びているTransition(下記画像の赤四角の矢印)を選択して
Inspectorの項目からHasExitTimeのチェックボックスをOffに、
そしてConditionsの「+」のボタンを押して下さい。
この「Conditions」での項目がTransitionの遷移条件を変数で設定する項目になります。
「+」を押したら先ほど作成した変数「TestInt」を追加。
変数名「TestInt」の右側の項目欄で「Equals」を選びその右に「1」と入れて下さい。
これはTestIntという変数が「Equals(=イコール)」「1」という条件を満たしたら遷移する、という設定になります。
要するにTestInt=1の時遷移するよ、という事です。
(その他の項目の詳細は後で記載しますね。)
同様に
Move01→Attack02に伸びているTransitionを選択して
Inspectorの項目からHasExitTimeのチェックボックスをOffに、そしてConditionsの「+」のボタンを押して
今度は「TestInt」「Equals」「2」と入れて下さい。
これでMove01から
TestInt=1の時はAttack01に
TestInt=2の時はAttack02に
遷移がするように条件が付けられました。
ちなみに、今回の他の遷移の設定は
「Idle」→「Move01」は
HasExitTimeのチェックをOnにしてExitTimeを0.9に
その他の設定は下記画像を確認して下さい(今回の内容にはそんなに重要では無いです)
「Attack01」→「Exit」へのtransitionの設定も
HasExitTimeのチェックをOnにしてExitTimeを0.9に
その他の設定は下記画像をこちらも確認して下さい。
(繰り返しですがそこまで重要じゃ無いです。デフォの設定のままでも大丈夫かと思います。)
※「Attack02」→「Exit」も同様の設定で構いません。
ここまでの状態で一度再生(ゲームプレイ)して確認してみましょう!
Move01から先に行かないふるね…
それもそのはず、いま「Parameters」タブの「TestInt」を見てみるとその値は「0」になっています。
Attack01、Attack02どちらの遷移の条件も満たしていないのでそこから先に遷移しないのは当然ですね。
ん?…ということはParametersの「TestInt」の値を変えれば上手くいくと思いましたね?その通りです。
ということでParametersタブから「TestInt」の値を「1」にしてもう一度再生してみましょう。
上手くいきました!Attack01に遷移しましたね。
(遷移する時に前後のアニメーションをブレンドしながら遷移しています)
同様に「TestInt」の値を「2」にして再生して見ましょう。
こちらも問題なさそうです!
これで条件によって遷移先をコントロールする事ができました!!
…ってこのままじゃ直接Unityを開いている時にしか変数変えられないじゃん!!そう思いましたよね?
え、そんな事ない?そんなぁ…
と、いうことで次の項目ではいよいよここまで組んだ遷移条件の変数をゲーム中に外部から制御して変数の値を変えていきましょう!
その前にちょっとTipsを挟むのじゃ、ふる。
TIPS:条件付けをしない時のアニメーション遷移条件は?
もし、Conditionsで遷移の条件を付けなかった場合どうなるでしょうか。
答えは簡単でステートで設定されている各遷移の優先度とTransitionのSettingsで設定されたExitTimeの設定に基づいて遷移されます。
ステートから複数のTransitionが伸びていた場合、優先度に基づいて遷移するTransitionが決定されます。
下記画像のようにステート「Move01」のInspectorのTransitionsという項目で書いてある遷移の上から順に優先度が高いものになります。(順番は任意で変えられます。)
そしてどのTransitionにするか優先度で決まったら(もしくは1つしか無かったら)TransitionのExit Timeの設定に基づいて遷移します。
ちなみにExitTimeもConditionsも設定が無いと、どちらかは必要だよ、って警告文が出るふる
4.外部から変数の値を変更
最後に、外部からAnimationParameterの変数にアクセスして数値を代入出来るようにします。
ここではボタンを二つ用意して、
赤いボタンを押すとTestInt=1に
青いボタンを押すとTestInt=2になるようにします。
1.ボタンの作成は「Hierarchy」ウインドウ上で右クリック→「UI」→「Button-TexteshPro」で作成できます。
2.Buttonを作成したらScene上かHierarchy上で選択、InspectorのImage項目「Color」を変えて赤色にしてあげましょう。
3.同様にして、青色のButtonも作成したら下記画像のようにゲームビュー上で左右になるように配置をします。
動かし方はScene上で直接つまんで動かしても、InspectorのRectTransformのPositionの数値をいじっても、お好みで。
赤いButtonを「Button1」青いButtonを「Button2」という名前にしました。
なお、現在のUnityのVerではButtonを作成するとButton内のTextはTextMeshProのシステムになっているので、今回は文字は使いません。
※Text MeshProは文字を使うのにフォントアセットというものを作成する必要があり、面倒なのでここでは使用しない
4.Buttonが作成できたので、Buttonを押したらTestInt変数が変わるようにスクリプトを仕込みます。
「Project」ウインドウで右クリック→「Create」→「C#Script」でスクリプトを作成。
名前は「Testint」(iは小文字)にしました。
作成した「Testint」スクリプトの中に下記のように記述します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Testint : MonoBehaviour
{
public Animator animator;
public void SetLevel(int testint)
{
animator.SetInteger("TestInt", testint);
}
}
このスクリプトを簡単に説明すると
public Animator animator;
の箇所でAnimatorコンポーネントの変数animatorを公開=Public設定で作成します。
public void SetLevel(int testint)
ではSetLevelメソッドでtestintという変数にint=整数の情報を入れてこのメソッド内の関数を実行してもらいます。
animator.SetInteger(“TestInt”, testint);
でanimator変数の中のTestInt(=Animatorパラメーター)にtestintの値を入れるという意味です。
5.このスクリプトをゲームオブジェクトの「Cube」にアタッチします。
「Project」ウインドウのTestIntスクリプトを直接CubeのInspectorにドラッグ&ドロップでアタッチ。
6.アタッチしたTestintコンポーネントの中の「Animator」という所の空欄をクリック→Animator Controllerに干渉したいゲームオブジェクト(ここではCube)を選択して下さい。
7.ここまでスクリプトのセットアップができたら、Buttonを押した時にゲームオブジェクト「Cube」にアタッチしたスクリプトの↓の部分に干渉できるようにしましょう。
public void SetLevel(int testint)
{
animator.SetInteger("TestInt", testint);
}
「Button1」のInspecotor内の「OnClick()」イベントリストで「+」アイコンをクリックして新しいイベントを追加。
イベントを追加できたら空欄(None)の部分にスクリプトをアタッチしたGameObject(ここではCube)をドラッグ&ドロップ、もしくは「◎」の部分をクリックして開いたウインドウから選択します。
空欄に入れたら、NoFunctionと書いてあるドロップダウンメニューから 「Testint」→「SetLevel
(int)」メソッドを選びます。
FunctionにTestint.SetLevelが入ったら、下の空欄に「1」と入れて下さい。
ここでの意味はクリック時にCubeのTestintスクリプトのSetLevelメソッドに1を引数(メソッド内の情報を処理するのに必要な数値)として渡しますよ、と言うことを指しています。
同様にして「Button2」の方もOnClickイベントを作成してTestint.SetLevelを「2」にしましょう。
これでボタンを押してアニメーションが分岐するシステムが完成しました。
試しにゲームプレイをしてみましょう。
Testintの値が赤いボタンで1に、青いボタンで2になりました!
上手くアニメーションも分岐しているようです。
これで条件によるアニメーション分岐の具体的な手順を終わりにします。
長かったけどこれで一通りの流れはわかったと思うふる!
アニメーションパラメーターの各項目詳細
遷移の条件付けの仕組みと、具体的な手順を見たところでParametersのそれぞれの変数がどのような条件になるか詳しく見て行きましょう。
Int
Int型(=整数)の値を格納できるパラメーターです。
1の時はこの条件、と言う風に各整数に振り分けても良いですし、ある数字以上にならないとこのアニメーションが発生しない(例えば連続攻撃回数とか)といった使い方もできます。
Trandition側で設定するConditionsではこのInt型に対して
・Greater
→設定した数字「より大きい」時に条件達成
・Less
→設定した数字「より小さい」時に条件達成
・Equals
→設定した数字「と同じ」時に条件達成
・NotEqual
→設定した数字「と同じでない」時に条件達成
の4つの条件を設定できます。
Float
float型(=浮動小数点型)の値を格納できるパラメーターです。
floatは細かい数字なのでキャラの移動スピードやダメージ量によるモーションの変更等、滑らかな遷移に使いやすい型です。
Trandition側で設定するConditionsではこのfloat型に対して
・Greater
→設定した数字「より大きい」時に条件達成
・Less
→設定した数字「より小さい」時に条件達成
の2つしかありません。
int型と違い、float型は小数点以下を扱う都合上、イコール処理が繊細になるからおそらく無いんだと思います。
Bool
bool型を格納できるパラメーターになります。
bool型ではtrue、falseの値(=真偽値)がParameters上ではチェックボックスのON、OFFで表現されます。
この型ではオンオフの2種類しか無いので、例えば特定のアイテムを持っている(=オン)時に特殊なアニメーションが発生したり、毒状態(=オン)の時に移動モーションが変わる、といった「ある状態になった時」と言うのを表現する時に使いやすいです。
Trandition側で設定するConditionsではこのbool型に対して
・true
→boolがオン状態の時
・false
→boolがオフ状態の時
の2種類しかありません。
シンプルだけど、使い勝手がいいのだ
Trigger
Trigger型を格納できるパラメーターです。Triggerはアクティブかアクティブじゃ無いかの2種類を持ち、Parameters上では丸ボタンで表現されます。
この型はboolと非常に似ていますが一度使用されるとリセットされるという特徴があります。
そのため攻撃ボタンを押したら攻撃モーションが再生される、特定の場所で決定ボタンを押したらイベントシーンが再生される、といった一度きりの使い方が有効です。
Trandition側で設定するConditionsではこのTrigger型に対して条件設定はありません。アクティブ時に自動で条件が達成されます。
boolとの違いをもう少しだけ補足しておくふる
TIPS:BoolとTriggerの違い
bool型とtrigger型は非常に似ていますが、
前述の通りboolはtrueかfalseかという状態を表現するので、遷移後もその状態を明確に変えることがなければtrueならtrueの状態のままです。
一方、trigger型はアクティブになって遷移がされたら、その時点でノンアクティブに自動でリセットされます。
繰り返しになりますが、
Triggerは遷移が完了したらOffになる。攻撃やジャンプといった1回使い切りのアニメーションに使用しやすく、
Boolは毒状態の時のモーションや、死亡時のモーション等「状態」を成否判定させてこの状態だったらこのアニメーション、という時に使いやすい設定になります。
TIPS:複数条件 andとor条件の作り方
折角なのでand条件やor条件の作り方も見ていきましょう!
・and条件の作り方
これは非常に簡単で複数の変数を作成したら必要な条件を全てConditionsにぶち込んであげれば良いでしょう。例えばAとBの両方の条件が達成されたら遷移するとしたい場合は下記のようにしてあげればヨシ。
勿論、ある数字が〇〇以上、かつ他の数字も〇〇以上、という時にも使用できますね。
また、ExitTimeとConditionsを併用することでもand条件になります。
・or条件の作り方
or(または)条件の場合は、Aの条件でも遷移し、Bの条件でも遷移させる必要があるのでTransitionを2つ引いてあげる必要があります。
まず、下記gifのように既にTransitionが引いてある箇所にもう一度Transitionを引いて下さい。
(ステートを右クリック→MakeTransition)
そして今作成した矢印が3つ重なったようなTransitionをクリック
するとInspectorのTransitionsと言う項目に先ほどの2つの遷移が表示されます。
それぞれの遷移を選択して、条件をつけてあげればどちらかの条件が達成された時点で遷移するので、or条件の完成です!
Parameter条件の制御方法いろいろ
本記事の具体的な設定方法ではParametersの変数は、UIのボタンからスクリプトを経由して制御しましたが、他の方法も含めて各Parameter変数への制御の仕方を見て行きましょう!
結局は変数の値を変更出来ないと何も使えませんからね…!
いろいろな方法を見ていこうふる!
UI(Button)からの直接制御
まずはButtonのみで制御する方法を記載しますね。
この方法はBool型やTrigger型のON \OFFを切り替えるタイプの変数のみで有効です。
具体的な手順方法で記載したOnclickイベントを作成する所までは同じです。
この時、下記画像のようにゲームオブジェクト→Animator→SetTrigger(string)を選択して下さい。
SetTriggerだけどBool型にも使えるのだ
そして、OnClickイベントの下の空欄にParametersで作成したbool型の変数名を記入しましょう。
これでスクリプトを通すことなく直接bool型の変数を制御することができます。
試しにゲームプレイして確認してみるとBool変数Aがボタンを押すとOnになリました。
※ちなみにBool型でOFFにするときはResetTrigger(String)の方をクリックイベントに入れればいけますよ!
同様に他のUI(スライダーやトグル等)でも同じことができます。
こういったシステムを「Parameter Binding」というみたいふる
スクリプトで制御
スクリプトでの制御方法は例で見せたゲームオブジェクトにスクリプトをつけてボタンで変数を制御するメソッドを呼び出す方法でほとんど説明ができているかと思います。
勿論、メソッドを呼び出すときはボタンで制御せずとも、スライダー等の他のUI機能であったり、何かのイベント(コントローラーやキーのボタンを押したら、とか所定の場所で特定の行動をしたらなど)に紐づいてメソッドが呼び出されるようにすれば機能します。
スクリプトとしては制作例の時は下記のように記述しました。
public Animator animator;
public void SetLevel(int testint)
{
animator.SetInteger("TestInt", testint);
}
public Animator animator;の所でどのゲームオブジェクトのAnimatorを参照するかの情報が必要なことには変わりませんが、
int以外の場合も、例としてあげていきます。
floatの場合は
public Animator animator;
public void SetLevel(float testfloat)
{
animator.SetFloat("Testfloat", testfloat);
}
boolの場合は
public Animator animator;
public void SetLevel(bool testbool)
{
animator.SetBool("Testbool", testbool);
}
triggerの場合は
public Animator animator;
public void SetLevel()
{
animator.SetTrigger("SetLevel");
}
と言うふうになります。※細かいスクリプトの記述ルールなどの説明は省きます。
スクリプトの超基本構造は下記を参考にしてみてほしいふる
TIPS:スクリプトとAnimationカーブの合わせ技
アニメーションイベントを使い、Animationが特定のフレームまで再生されたら自動でスクリプトからメソッドを呼び出し、変数を制御する、という方法もあります。
仕込みたいアニメーションクリップのAnimationウインドウの任意のフレームでイベント追加ボタンを押して下さい。
追加したイベントをクリックするとInspectorでFunctionが選べるようになっていると思います。
※イベントを追加したAnimationのゲームオブジェクトにスクリプトがアタッチされている必要があります。
ここでFunctionからスクリプト名→methods→メソッド名を選んであげればOKです。
終わりに
今回はAnimator Controller (アニメーターコントローラー)内でのParameterとConditionsを使ったアニメーションの条件分岐を見て行きました。
これで、例え無数のどんな事が起きようともそれに合わせたアニメーションが再生されますね!
いやいや、アニメーションを無数に用意するのは無理ふるよ…?
◾️その他のUnityアニメーション関連のマトメ記事はこちら
えきふるからのご相談!
当ブログ「えきふるゲームラボ」では出来るだけ分かり易く読みやすい記事の作成を目指しています!
もし読んでくださった方の中で
「ここが良く分からなかった」「ここをもう少し掘り下げて欲しい」等ありましたら
ぜひコメントで教えて下さい!
コメント貰えると元気も出ますので、どうぞお気軽にお願いしますふる!
※このブログは、UnityTechnologiesまたはその関連会社が後援または提携しているものではありません。「Unity」は、UnityTechnologiesまたはその関連会社の米国およびその他の国における商標または登録商標です。
コメント