その1:https://qiita.com/mas-yo/items/43101d2e5ef073a1f3f5
その2:https://qiita.com/mas-yo/items/f802b5a6a6b3f47eed71
その3:https://qiita.com/mas-yo/items/cd0ddfebba3348a98b24
前回はECS(Entity Component System)を用いてゲームの設計を始め、土台となる部分ができるとこまでやりました。
引き続き、その1,その2でオブジェクト指向で考えて来たゲームのアップデートを、ECSでやるとどうなるか、見ていきたいと思います。
前回までで、下記の様な設計になっています。
1ヶ月後
さて、開発が始まって1ヶ月が経ちました。ここで企画から「空を飛ぶ敵を作りたい」という要望が来たとします。
空を飛ぶ敵の要件は
- 障害物の上を通れる
- プレイヤーの物理攻撃は当たらない
- アイテムをドロップする際は、周囲の通れる場所にドロップする。
まず「障害物の上を通れる」を設計してみます。
これまで、そもそも障害物という概念もなかったので、そこから考えます。
新たに MoveAttribute
コンポーネントとGroundCollider
コンポーネントを追加しました。
MoveAttribute
コンポーネントは、キャラの移動属性で、地面を歩くか空を飛ぶかの情報を持っています。
GroundCollider
は、そのステージに1つだけ存在し、地面のコリジョン情報を持ちます。
そして、Velocity
システムが、これら2つのコンポーネントを参照し、「ぶつかったらその位置で止まる」という処理を行います。
- プレイヤーの物理攻撃は当たらない
攻撃の当たり判定は、DefenseColliderシステムで行っています。これがMoveAttributeを参照すればOKですが、ここで1つの疑問が浮かびます。仕様では、「プレイヤーの物理攻撃が、飛んでいる敵には当たらない」です。
では、「プレイヤーかどうか」というフラグをどこかに持って判定すべきなのでしょうか?もちろん、答えはNOですね。この仕様の意図するところは、地上→空への物理攻撃が当たらない、ということです。(一応、プランナーに確認を取っても良いですね)
よって、MoveAttributeを参照すれば良いということになります。これで、もし将来空を飛ぶプレイヤーができた時は、空への攻撃も可能になるはずですね。
ところで、もしこれをオブジェクト指向で実装した場合、Player
Enemy
といったクラスがありますから、そのまま素直に実装すれば、Player
クラスからEnemy
クラスへの攻撃で、敵が空を飛んでいた場合、という条件判定にしてしまいがちです。
でもそれだと、空を飛ぶプレイヤーが出てきたときに破綻してしまいますね。ECSで設計すると、機能単位で実装が分かれるため、仮にあいまいな仕様が来たとしても、実装する段階でそれを具体的な機能に落とし込むことになります。これによって、本来意図するところの機能が、正しく実装されることが期待できます。
- アイテムをドロップする際は、周囲の通れる場所にドロップする。
こちらも、ドロップの機能が設計できる前提の仕様です。
意図するところは、「今までは空を飛ぶ敵がいなかったので、死んだその場にアイテムをドロップしていた。今回空飛ぶ敵が現れた事で、その場にドロップしてしまうと、通れない場所にドロップする可能性が出てきてしまうため、周囲の通れる場所を探してドロップするようにしたい」ということですね。
今進めているECSによる設計では、まだドロップの実装をしていませんので、そこから考えることになります。
そのドロップのシステムが、前述の GroundCollider
を参照して、ドロップする場所を決定するようなロジックを組めば大丈夫そうです。
この機能の実装については、詳細を省略します。
次は、開発2ヶ月後、
「羽のアイテムを使うとプレイヤーは空を飛べるようにする」
という仕様が生まれた事を想定して、設計を考えてみます。
次回につづく・・・