Aizu-Progressive xr Lab blog

会津大学のVR部であるA-PxLの部員が持ち回りで投稿していくブログです。部員がそれぞれVRに関する出来事やVRにちなんだことについて学んだことを書いていきます。

「面白法人カヤックVR分室」としても活動しています。詳細はこちら

敵の編集を楽にしようと頑張ったお話

始め

Aizu-PxLの修士になりました、なおしです。
皆さんは敵の動きをどのように作成しますか?

  • プログラムを書く
  • NavMeshを使う
  • ランダムに動かす
  • etc

今まで私はこれらを活用して敵を作成したことがあります。ゲームにおいて敵の存在は切っても切れない存在だと思っていますが、作る上ではとても厄介なものだと感じています。

今回の内容は前半にこれまでの経験、後半に今やっていることをまとめます。

今まで敵を作成して感じたこと

NavMeshを使ったとき

敵をプレイヤーに向かわせるときNavMeshを使用することが多いと思います。もしくはプログラムでも実装するのはそう難しくはないかもしれません。

NavMeshを使用した際の利点として

  • 敵は必ずプレイヤーに向かう
  • プログラムを書くのが楽
  • 様々な敵の種類にも適用できる

があります。

しかし、ただプレイヤーに向かうだけの敵は想像以上に飽きるのが速いです。 また、NavMeshの弱点として地面に接地しない敵には使うことが出来ないところです。NavMesh使うのはプレイヤーを探索する時だけにして、一定距離に近づいたときに別の行動をするアルゴリズムにしたほうが面白くなるかなと思っています。(その分、作業量が増える)

個々の敵をプログラムする

個々の敵に対してプログラムを書くことによって

  • 様々な動きをする敵が作れる
  • 飽きにくい
  • 敵の種類に応じて動きを作成できる

という利点が生まれます。

しかし、プログラムで敵を動かす際に発生する欠点は

  • プログラムが複雑化したり、デバッグが大変になる
  • ゲームバランスの調整が難しい
  • 敵の種類を増やしにくい

と感じます。NavMeshを使ってプレイヤーに向かわせる、そこから敵に攻撃、プレイヤーが逃げたら追跡等モンスターの動きの幅が広がる一方でかなり編集に難があると思います。

ランダムに動かす

ランダムに敵を動かすプログラムを作るのは簡単ですが、それもアルゴリズムによりけりかなと感じました。例えば、Random関数などを使ってその方向に動かすとすればすぐに書けます。しかし、そのプログラムで動く敵はブルブル震えるだけになるでしょう。

アルゴリズムを考えて壁にぶつかるまで前進して、ぶつかった際はランダムで方向転換、そして前進するようなものにすればそれっぽく動くようになります。

ランダムに動かす場合の一番の問題点としてはゲームバランスの調整が先の2つに比べてかなり難しくなることだと思います。

簡単な総括

今までの開発経験を通して次のことが言えるのではないかって思っています。

  • 簡単にプログラムされた敵は編集、開発は楽であるが飽きやすい
  • 複雑なプログラムで作成された敵は飽きにくいが編集、開発が難しい

今やろうとしたこと

只今私は個人開発をしているのですが、その中で簡単に敵の動きを編集できるものを作ろうと頑張っています。だた、まだ完成してませんし完成する目途がまだ立っていない状態なのでご了承ください。

動きをクラスにする

今までは1つのプログラムに様々な動きを書いていました。そのプログラムを改良やリファクタリングした結果、敵の動きをクラスで表現するという結論に至りました。簡単なクラス図は次のようになります。

f:id:aizu-vr:20190603000933j:plain

まず、Monsterクラス、MonsterActionクラスを作成します。MonsterクラスはMonsterActionクラスのリストを保持します。MonsterActionクラスにはAction関数があり、MonsterActionクラスを継承したクラスはAction関数をオーバーライドします。最後にMonsterクラスはリストに入ったMonsterActionクラスのAction関数を呼び出し、多態性によりMonsterActionクラスを継承したクラスのAction関数を実行することが出来ます。


解説すると意味がわかりませんね。簡単に言うと動き(攻撃、移動など)をリストに保存してそれを順に実行していくということです。
ちなみに、このようなデザインパターンStateパターンと呼ぶそうです。
追記:もしかしたら違うかもしれません。間違っていたらごめんなさい

これらを参照しました。

ゲームプログラミングC++

ゲームプログラミングC++

増補改訂版Java言語で学ぶデザインパターン入門

増補改訂版Java言語で学ぶデザインパターン入門

エディタ拡張ReorderableListを使う

コンポーネントのリストをエディタで編集しようとすると結構めんどくさいです。また、今回はMonoBehaviorを継承していないものを編集するため普通のInspectorでは編集できません。

f:id:aizu-vr:20190603004259p:plain
要素の追加、入れ替えが面倒。そして見にくい

そこでReorderableListを使用したいと思います。

f:id:aizu-vr:20190603004555p:plain
Unityで見たことあると思います

これを使用することにより型によって表示する枠を変えたり、要素の入れ替えや追加が簡単になります。

ReorderableListについてやエディタ拡張については次を参照しました。 Unity エディター拡張入門

また、一度別の個人開発でも使用しました。Fire Commander!

今起きている問題

だた、まだこれが完成していません。今起きている問題が派生クラスの型が消えて基底クラスの型として表示されることです。始めは上手く動作しますが、リビルドされた際に型が消えてしまうというバグに悩まされています。

デバッグ用にメンバ変数(派生クラスも含む)をすべて表示する関数を用意しているのですが、それも派生クラスの関数が呼ばれていないので保存されているデータとしても基底クラスに変わっていしまっているみたいです。

過去に使った際は一つのクラスだけのリストでしたが今回はいくつかの派生クラスを保存するのでダウンキャストをしなければなりません。そして、UnityEditor上でどのようにデータが保存されているかまだ理解できていないことが原因だと思います。

解決策

考えうる解決策としてデザインパターンの変更を検討しています。Monsterクラスに保存するものをデータの構造体に変更し、そのデータを一度Factoryクラスに渡してMonsterActionクラスを生成するクラス図を考えています。

欠点としてデータの構造体にすべての動きに対応できるほどのメンバ変数を用意しないといけないこと、新しいMonsterActionクラスを作成した際にFactoryクラスも修正しないといけない点です。

最後に

みっともない話ですが、まだ今やろうとしていることが完成せずにブログにまとめています。ただ、エディタ拡張、デザインパターンを習得する価値は非常に高いと感じています。

この2つを使うことによってゲームの仕様変更やゲームバランスの調整、拡張が容易になるはずです。これからこれらも勉強していきますし、完成次第もう一度ブログにまとめ直す予定であります。

完成するまで応援して欲しい。

会津大学VR部の部員が持ち回りで投稿していくブログです。特にテーマに縛りを設けずに書いていきます!