はじめに
今回はUnityのC#を用いて2Dアクションゲームのアニメーション制御をしたいと思います。プレイヤーが立ち絵から走る状態への遷移をAnimatorやスクリプトを用いて実装していきます。アニメーション自体の作成は終わっているとの前提で話します。
※Unityはバージョンアップの頻度が多く、メニューやレイアウト、表示が変わっていることがあります。
<アニメーターコントローラー>
Animator Controllerの中身を見ていきます。Unity上部メニューのWindow>Animation>Animatorをクリックしてください。この状態で作成したゲームキャラクターのオブジェクトを選択してください。すると、ゲームオブジェクトについているAnimatorのコンポーネントの中身を表示してくれます。
<遷移を矢印でつなげよう>
AnimatorにAnimationを入れる
さて、アニメーションを状況によって切り替える準備をしたいと思います。アニメーターウィンドウでオレンジ色になっているものがありますでしょうか。そちらはデフォルトのアニメーションです。今回の場合は、デフォルトで「立ちモーション」を設定してほしいです。
デフォルトのモーションを変更したいときは、デフォルトにしたいアニメーションを選択して右クリック>Set as Layer Default Stateを押せばそこがオレンジ色になります。
アニメーション遷移を描こう
それではアニメーションの制御をしていこうと思います。
左ボタンか右ボタンが押されたら走るとした場合、押される前は立ちモーションで、押されたら走りモーションにしたいので「立ち」と「走り」をつなぎます。立ちモーションを選択して、右クリック>Make Transitionを選択します。そしたら、何やら矢印のようなものが出てくると思いますが、そのまま走りモーションをクリックしてください。遷移矢印が引かれたと思います。
矢印をちゃんと引けたら、矢印をクリックしてください。この時、インスペクターのHas Exit Timeのチェックを外してください。Has Exit Timeというのは、アニメーションがすべて再生し終わったら次のアニメーションに遷移するという意味です。今回は左ボタンか右ボタンが押されたら即座に反応してほしいのでHas Exit Timeを切ります。
次にSettingとなっているところの▶をクリックして展開してください。何やら色々出てきましたが、この部分はアニメーションとアニメーションを合成する項目です。これは3Dアニメーションを作成したときに使用する項目で、2Dアニメーションでは合成をしてほしくありません。Transition Durationを0にしましょう。これで合成しなくなります。下のほうに警告文が出ていますが、「遷移が有効になるには、少なくとも1つの条件または終了時間が必要です。それ以外の場合は無視されます。」と言っています。矢印を通る条件がありませんよということです。と、いうわけで矢印を通る条件を入れましょう。
Animatorウィンドウ左上のParametersをクリックします。上のほうに出てきた「+」をクリックしましょう。これで何のパラメータを追加するのかを聞いています。今回の場合、ボタンを押している間走って、ボタンを離している間止まって欲しいので、これが表現できるBool型を選択し、名前をrunとします。
次に矢印をクリックして、インスペクターを見てください。Conditionsのところの「+」をクリックしてください。左側にパラメータ名、右側に値が何だったら条件に当てはまるかが表示されています。変更したければそこをクリックします。今回は、パラメータ「run」が「true」になったら立ちモーションから走りモーションに遷移するようにしたいと思います。つまり、左ボタンか右ボタンを押されたらパラメータ「run」をtrueにすれば走ります。逆に離したら止まりたいので反対も作成しましょう。
今度は走りモーションから立ちモーションへ矢印を引きます。新しく引かれた矢印をクリックして、同じようにHas Exit Timeのチェックを外して、Transition Durationを0にしました。その後Conditionsの+を押してパラメータを追加します。今度は反対に条件をfalseにします。これで、左ボタンか右ボタンを押されたらパラメータ「run」をtrueにし、キーを離したらfalseにするようにすれば走る表現をすることができます。
<スクリプトで制御しよう>
スクリプトを作ってAnimatorを取得
それではスクリプトから左ボタンか右ボタンを押されたらパラメータ「run」をtrueにし、キーを離したらfalseにするようにしたいと思います。とりあえず、スクリプトを作成し、Animatorを貼り付けたゲームオブジェクトにアタッチします。スクリプト名を「Player」にします。アタッチが完了したらスクリプトを書き始めましょう。
private Animator anim = null;
void Start()
{
anim = GetComponent<Animator>();
}
まずは同じゲームオブジェクトに設定されたAnimatorのインスタンスを取得し、変数に突っ込みます。
現在のキー入力の設定を見てみよう
次にキー入力をみましょう。上部メニューのEdit>Project Settingをクリックします。次に出てきたウィンドウの左メニューのInput Managerをクリックしてください。このHorizontalというのが水平方向の入力を表します。Negative Buttonがleft、Positive Buttonがrightとなっているのがわかるでしょうか。これは、水平方向のマイナス方向のボタンは「left」とし、プラス方向のボタンは「right」とするという意味になります。leftは「←」キー、rightは「→」キーです。
プログラムにキー入力を書いてみよう。
これが確認できたら今度はUpdateにプログラムを書いていきます。Upudateは「毎フレーム処理を行う」ので、この場所に「もし左ボタンか右ボタンを押したら」と記述します。そうすることで、毎フレーム、ボタンを押したかどうかを監視することができます。
private Animator anim = null;
void Start()
{
anim = GetComponent<Animator>();
}
void Update()
{
float horizontalKey = Input.GetAxis("Horizontal");
if (horizontalKey > 0)
{
anim.SetBool("run", true);
}
else if (horizontalKey < 0)
{
anim.SetBool("run", true);
}
else
{
anim.SetBool("run", false);
}
}
float horizontalKey = Input.GetAxis("Horizontal");
これは、Input Managerの「Horizontal」と書いてあったところを表します。水平方向のマイナス方向のボタンに設定したキーを押されると、マイナスになり、プラス方向のボタンに設定したキーを押されるとプラスになります。それを変数に入れているわけです。
else if (horizontalKey < 0)
{
anim.SetBool("run", true);
}
これの「horizontalKey < 0」は「もしマイナスならば」という意味ですので、マイナス方向のボタンを押したことになります。初期設定はマイナス方向のボタンは"left"という奴になっているはずです。これは「←」キーを表すので、「もし←キーを入力すると」という意味になります。
アニメーターのパラメータを変更しよう
さて、キー入力を判別できるようになったらアニメータのパラメータを変更しましょう。
anim.SetBool("run", ture);
というのはAnimatorのコンポーネントのインスタンス(実体)にアクセスしてBool型のパラメータの値を変更するという意味になります。引数に("run",true)としているのは先ほど自分で作ったパラメータ「run」をtrueにするという意味になります。つまり、スクリプトの部分は、
float horizontalKey = Input.GetAxis("Horizontal");
if (horizontalKey > 0)
{
anim.SetBool("run", true);
}
else if (horizontalKey < 0)
{
anim.SetBool("run", true);
}
else
{
anim.SetBool("run", false);
}
もし右ボタンが押されたらアニメーターのrunをtrueに、左ボタンを押されてもアニメーターのrunをtrueに、右ボタンも左ボタンを押されていなければrunはfalseにしています。この状態で再生すると右か左ボタンを押したとき、runがtrueになって、走り出すようになりました。
しかし、これでは右ボタンと左ボタンのどっちを押しても右側に走っていってしまいます。そのため、左ボタンを押された時は左右反転をするようにします。
float horizontalKey = Input.GetAxis("Horizontal");
if (horizontalKey > 0)
{
transform.localScale = new Vector3(1, 1, 1);
anim.SetBool("run", true);
}
else if (horizontalKey < 0)
{
transform.localScale = new Vector3(-1, 1, 1);
anim.SetBool("run", true);
}
else
{
anim.SetBool("run", false);
}
実は、transformの大きさをマイナスにすると反転します。今回は左右反転させたいので、xをマイナスにします。大きさを変更するにはtransform.localScaleで大きさを変更できます。
transform.localScale = new Vector3(-1, 1, 1);
今は自分たちはインスペクターから値を触れますが、当然ゲームを遊ぶプレイヤーは触れないので、プログラムからキー入力で値を触れるようにしてあげないといけません。また、左を向きっぱなしになっても困るので右ボタンを押したら右に向き直してもらうために、
if (horizontalKey > 0)
{
transform.localScale = new Vector3(1, 1, 1);
anim.SetBool("run", true);
}
としています。この状態で再生してみましょう。はい、これで走れるようになりました。アニメーションの制御に関してはだいたいこんな感じです。
おわりに
いかがでしたでしょうか。歩きから走りのモーション移動だけでもこれだけのロジックが組まれています。ゲームを作るとなると途方もないロジックになりそうですが一つずつ組み立てていけば作れるので頑張っていきましょう。
投稿者
エンジニアファーストの会社 株式会社CRE-CO 田渕浩之