[Departure from the Void] 敵の動きクラスを整理

昨日からステージに配置する敵の動きを本格的に実装し始めました。
今日はこの敵の動きを効率的に管理できるようにする仕組みを実現するため、敵の動きを管理するクラス周りの見直しを行いました。

以下、出来上がったクラス図です。

20170221_1

かなり複雑になってしまいましたが、これで概ねこのゲームでやりたい動きの管理はできるようになりました。
今回このクラス構成にした意図は以下の通りです。

  • 最小単位の動きはUnityのインスペクタから設定できるよう、Serializableなクラスを継承させる
  • 直線やカーブといった最小単位の動きを順番に行う仕組みにする
  • 最小単位の動きは時間や距離で終了できる(次の動きに切り替えられる)ようにする
  • 動きの一部は敵弾の発射時の初速指定ができるようにする
  • 進行方向に敵を向かせられるようにする

直線やカーブは、MotionBaseというSerializableなクラスを継承させて実装するようにしました。
当初はIMotionというinterfaceクラスを継承させていましたが、interfaceクラス型のフィールドはUnityのシリアライズ対象にならないため、苦肉の策としてこのような継承関係になりました・・・

最小単位の動きはこのMotionBaseクラスを継承したLinerMotion、CurveMotion、ChargeMotionクラスなどで実装します。

これらの最小単位の動きは、~MotionInvokerというクラスが責任をもって実行させるようにしました。
これは最小単位の動きを順番に実行させる必要があったためです。
最小単位の動きを順番に実行するクラスはSequenceMotionInvokerが行います。
単一の動きでよい場合はSingleMotionInvokerが行うようにしました。

最小単位の動きは、IMotionConditionクラスが監視し、終了させるようにしました。
MoveByTimeクラスは指定時間経過したら、MoveByStanceクラスは指定距離移動したらIMotion.End()を実行し、動きを終了します。
このタイミングで~MotionInvokerが終了通知を受け取り、次の処理に移れるようにします。
SequenceMotionInvokerはこれで次の動きを実行(IMotion.Begin()を実行)します。

最小単位の動きクラスのうち、敵弾として使用可能な動きはIShootableクラスを継承するようにしました。
このクラスのSetVelocity()、GetVelocity()を実装することで、敵弾の初速の設定・取得ができるようになります。
弾幕を張る場合は弾それぞれの速度が異なるため、敵弾の発射者が柔軟に弾速を設定できるようにした方が望ましいからです。

そして、敵弾含め、移動する方向にスプライトを回転できるようにForwardRotationという動きクラスを置きました。
このクラスがIShootable.GetVelocity()を随時実行しながら速度を監視し、スプライトを動く向きに回転させる処理を行います。

 

今回この敵の動きクラスを設計して得た教訓は、Unityのインスペクタ上でクラス間の紐付けができることも考慮して設計すべきということです。
(理想はinterfaceクラスもUnityのシリアライザが扱えるようになることなのですが・・・笑)
逆にインスペクタ上での紐付けが必要ない場合はinterfaceクラスを積極的に活用した方が良いかもしれませんね。