Unityで2D格闘(2D Fighting game)作るんだがアニメーターを使えば状態遷移ラクチンだなという話し

  • 0
    いいね
  • 0
    コメント

    201701210647gif30.gif
    アニメーター便利なんだが 使い方わからんから使ってない とか言ったりして もったいないことしてないだろうか?

    ソース公開中 Open sources

    https://github.com/muzudho/KifuwarabeFighter2

    アニメーターって何?

    201701210653a49b.png
    この グラフみたいなやつが アニメーター。 別に、アニメ以外のことにでも使える。本来は……、
    201701210653a50.png
    Aボタンを押したら 剣を振る、 剣を振ってる最中は Aボタンを押しても 反応を受け付けない、といったことを 図にしたものだ。

    アニメーターというだけあって、1フレームごとに反応 してくれる。そして実際に 剣を触れるときにAボタンを押したら剣を振り、剣を触れない時にAボタンを押しても反応を受け付けないといった機能を持つので、これは便利だ。使っていくことにした。

    何が便利なのか?

    これは ジャンプキック したときの動きだ。
    201701210647gif31b.gif
    ジャンプの下降中にダメージを受けた、とか 1フレーム単位で証拠を見せつけられているようで 「ぬぐぐ!」 という感じだ。バグでも出そうものなら「アニメーターを使って確認しろよ!」とかユーザーに言われちゃったりして プログラマーはどんどん働かされるだろう。つらい。

    「どの状態のときに」(ステート)、「どうした」(トリガー)という想像は これからは図に描ける。
    201701210653a52.png
    箱と 矢印 になっていて、つなげられるので、動きの流れが言語化 された。

    201701210653a54.png

    箱と線という言葉 がプログラムを組む上で 即、実用できるものになった。
    これで、

    ここに線が足りないのでは、
    もう1つ箱が要るのでは、

    といった 会話 が 「いえ、実はプログラムの中ではそのようになっていないんで……」などということがなく、「はい、線を張り替えます!」といったことが実用できるものとなった。プログラマーはつらい。

    欠点は?

    あの箱と箱を結ぶ白い線、1本1本 マウスで引っ張って くっつけてるんで。まだ立ち、しゃがみ、ジャンプ、ブロック、ダメージ、数百本以上 張らないといけないんで。

    ジャンプの頂点から パンチ、キック6種類をつなげる、とか 束ねて命令できずに マウスで 6回線引かないといけないんで。なんというか 非プログラマー的行為だ。

    プログラムを、アニメーターに置き換えよう。

    きふわらべファイター2のソースコードは もうリファクタリングした。Unity の Animator を積極的に使っている。

    アニメーターを使おうぜ

    もうリファクタリングしてしまったので、一から説明するのではなく、セレクト画面のリファクタリング中に撮っていた画像を使って 振り返りながら解説する。
    201701201621a31.png
    アニメーターを新規作成すると、[Any State]、 [Entry]、 [Exit] という3つの箱だけがある。感覚的には……。

    201701210653a53.png
    絵にしたことに意味があるのかどうか分からないが、アニメーターというのは いっぱいあって、1個で完結しているアニメーターもあれば 外側から利用されているアニメーターもある。最初はとりあえず [Entry] を使うところから始めればいい。

    201701201621a32.png
    カーソルが止まっている状態を Stay、 カーソルが隣の欄に動いている最中を Move とすればどうだろうか。
    Move 中は レバー入力も ボタン入力も無効とする。

    201701201621a36b.png
    まずは カーソル画像(SengoとかGoteとか)に 空っぽのスクリプトを持たせ、
    この空っぽのスクリプトから アニメーターを呼び出せるようにした。

    201701201621a38b.png
    矢印には move など、その矢印を通るための符牒を決めておく。これをトリガーという。

    201701201621a39.png
    箱が足りない、線が足りない、トリガーが足りない、と思えば あとから追加できる。

    なんちゃってデータベース を自作しよう

    201701201621a40b.png
    ここで わたしの流法(つまり我流)なんだが、Unity の Animator とは別個に 列挙型を手打ちで用意した。 ステートを 名指しするのに使う。この列挙型を 我流で インデックス と呼んでいる。配列の添え字(インデックス)のように使うからだ。

    201701201621a41.png
    また、1つ1つの ステート がデータを持てるように struct(構造体)を用意しておく。今は名前ぐらいしか入れるものがないが。

    201701201621a42.png
    そして 定型文で こんな感じのソースを貼りつける。

    201701201621a43b.png
    ここに データ を手打ちしていく。現在のステートから このデータを引っ張ってくるところまで 一連の流れで作成する。 これを Aステート・データベース と名付けている。Aというのは アニメーター のことだ。 でも呼びにくいので なんちゃってデータベースでいいか。

    201701201621a44b.png
    シーン開始時に なんちゃってデータベース を初期化したいんだが、どこに書くのかいまいち いいところが分からないので メインカメラの Start( ) メソッドで初期化するように書いている。

    201701201621a45.png
    で、結局 一番欲しいのが この GetCurrentAstateRecord( ~ ) メソッドだと思うんだが、アニメーターの現在のステートがどこかに応じて、 なんちゃってデータベース のデータを返してくれる。ここまで自動化。 コードまで自動で作ってくれたらもっと楽なんだが☆

    プレイヤーのスクリプトで使おう

    自作した なんちゃってデータベース の使い方を説明する。
    201701210422a46.png
    これだけ。

    アニメーターをアタッチしているゲームオブジェクトに、スクリプトもアタッチしておいて、
    Update( ) メソッドの最初に データを取り出すだけだ。

    201701210647gif30.gif
    作り方には いくぶん我流が含まれるものの、
    アニメーターの利用の仕方は 見えてきたのではないだろうか。