20. Physics.Arcade.Group
はじめに
敵や弾など、似たような挙動をする多数のスプライトを扱うとき、個々にコリジョンを設定するのではなく、Phaser.Physics.Arcade.Group を活用することでコードをスッキリさせつつ、効率的に物理演算を行うことができます。
グループを使ったコリジョン設定の利点
例えば、プレイヤーと敵が接触した際に処理を行いたい場合、次のようなコードになります。
// グループ作成
this.playerGroup = this.physics.add.group();
this.enemyGroup = this.physics.add.group();
// プレイヤーや敵をグループに追加
this.playerGroup.add(playerSprite);
this.enemyGroup.add(enemySprite);
// コリジョン(オーバーラップ)設定
this.physics.add.overlap(this.playerGroup, this.enemyGroup, this.handlePlayerEnemyOverlap, undefined, this);このようにグループ同士で overlap を設定することで、すべてのスプライト間の接触を一括で処理できます。
注意点:グループに追加すると状態が初期化される
ただし注意すべき点があります。Arcade.Group にスプライトを追加したタイミングで、そのスプライトの物理プロパティ(特に velocity や acceleration)が初期化されます。 たとえば、以下のようにすると問題が起こる可能性があります。
enemySprite.setVelocity(100, 0); // ← ここで速度を設定
this.enemyGroup.add(enemySprite); // ← 追加した時点で velocity が(0,0)にリセットされる
これに気づかず、バグに悩まされました。
対策1:追加後にプロパティを設定する
グループに追加した後にプロパティを設定するようにします。 ECSの場合、グループに追加のあとにVelocityを変更するように、システムの設計を見直す必要があります。
this.enemyGroup.add(enemySprite);
enemySprite.setVelocity(100, 0);対策2:グループ追加時の初期化を防ぐ方法
別の解決法として、group.defaults に明示的に空オブジェクトを指定することで、この初期化を無効化できます。
const enemyGroup = this.physics.add.group();
enemyGroup.defaults = {}; // 初期化されないように設定
enemyGroup.add(enemySprite);この設定をしておけば、add() 時にスプライトのプロパティが意図せず書き換わるのを防げます。 ただし、オブジェクトプールでスプライトの使い回しする場合には、初期化しないことで意図せぬ問題が発生することもあります。 (後述のリサイクルパターン)
その他の補足ポイント
GameObjects.Group vs Physics.Arcade.Group の違い
GameObjects.Group は物理演算を持ちませんが、Physics.Arcade.Group は自動で物理ボディを付与します。 コリジョン設定する場合は、Arcade.Group を使います。
create()
group.create() の基本的な使い方
const enemyGroup = this.physics.add.group({
defaultKey: 'enemy',
defaultFrame: 0,
});
// 指定位置に新しいスプライトを生成し、グループに追加
const enemy = enemyGroup.create(100, 200);
enemy.setVelocity(100, 0);ここでは defaultKey と defaultFrame を設定しているため、create(x, y) だけでスプライトを生成できます。 classType を設定することもできます。(独自のEnemyクラスを使う場合など)
createMultiple()
createMultiple() を使うと、同じ種類のスプライトをまとめてグループに生成・追加できます:
this.enemyGroup.createMultiple({
key: 'enemy',
repeat: 5,
setXY: { x: 100, y: 100, stepX: 50 }
});setXYのx,yは最初の座標です。stepX=50なので、xは100,150,200,250,300 と変化します。
getChildren()
getChildren() でグループ内のすべてのスプライトにアクセスし、まとめて設定を変更できます:
this.enemyGroup.getChildren().forEach((enemy: Phaser.GameObjects.Sprite) => {
enemy.setAlpha(0.5);
});get() とリサイクルパターン
毎回 new でスプライトを作成せず、非表示になったスプライトを再利用することで、パフォーマンスが向上します。
group.get() は使われていない(active = false)スプライトを再利用する仕組みです。大量のオブジェクトを繰り返し生成・破棄するのを避け、パフォーマンスの向上に繋がります。
使い終わったスプライトは setActive(false) と setVisible(false) にしておくことで、次回 get() 時に再利用されます。
const bullet = this.bulletGroup.get(x, y);
if (bullet) {
bullet.setActive(true).setVisible(true);
bullet.setVelocity(0, -300);
}まとめ
Arcade.Groupについて整理しました。