スポーン
シングルプレイヤーでは、シーンをインスタンス化するとローカルノードが作成されます。マルチプレイヤーでは、同様の操作ですべてのクライアント上にノードを作成し、レプリケーションシステムが追跡できるネットワークIDを割り当てる必要があります。これがスポーンの役割で、ローカルでのシーンのインスタンス化を、すべてのピア間で連動するイベントに変換します。
デスポーンはその逆です。すべてのクライアント上でオブジェクトを削除し、ネットワークIDを解放します。途中参加したクライアントは、ルームに入った際、スポーンしているオブジェクト一式を自動的に受信します。
セットアップ
FusionSpawnerは、すべてのクライアント上でオブジェクトの作成/破棄を行うネットワークファクトリーとして機能します。シーンにFusionSpawnerを追加し、スポーンしたいシーンを登録してください:
GDScript
const PlayerScene = preload("res://player.tscn")
const ProjectileScene = preload("res://projectile.tscn")
@onready var spawner = $FusionSpawner
func _ready():
spawner.add_spawnable_scene(PlayerScene)
spawner.add_spawnable_scene(ProjectileScene)
spawner.spawned.connect(func(n): print("Spawned: ", n.name))
spawner.despawned.connect(func(n): print("Despawned: ", n.name))
スポーンしたいオブジェクトのspawn_pathを親ノードに設定します(デフォルトはFusionSpawnerの親です)。
すべてのクライアントは、スポーンしたいシーンを同じ順序で登録する必要があります。
スポーンとデスポーン
ネットワークオブジェクトを作成するにはspawn()を呼び出します。すべてのクライアント上から削除するにはdespawn()を呼び出します。
GDScript
# 最初に登録されたシーンをスポーンする
var player = spawner.spawn()
player.position = Vector2(100, 200)
# 特定の登録されたシーンをスポーンする
var projectile = spawner.spawn(ProjectileScene)
# デスポーンする
spawner.despawn(player)
スポーン後にノードのプロパティを設定してください。複製対象のプロパティ(FusionReplicationConfigで設定)は次回のネットワーク更新に含まれます。
シーン構造
一般的なゲームシーンにはゲームロジックとFusionSpawnerが含まれており、スポーンできる各シーンにはルートノードの子ノードに複製ノード(トポロジーによってFusionSharedReplicatorかFusionServerReplicator)が含まれています。


プロパティ
以下のプロパティでは、スポーンしたオブジェクトがツリーのどこに配置されるか・どのシーンが利用可能かを設定できます。
spawn_path(NodePath,"..") - スポーンするオブジェクトの親spawnable_scenes(Array[PackedScene]) - 登録されたスポーン可能なシーン
シグナル
FusionSpawnerは、すべてのクライアント上でオブジェクトが作成/破棄された際にシグナルを発火します。
spawned(node: Node)- オブジェクトがスポーンした(ローカル/リモート)despawned(node: Node)- オブジェクトがデスポーンした
複製ノードごとのspawned
複製ノードも各自でspawned()シグナルを発火し、FusionSpawnerシグナルを補完します。シグナルのハンドラーがFusionSpawnerの親ノードではなく、複製ノードで反応する必要がある場合(例:複製されたルートにアタッチされたスクリプトなど)は、複製ノード自体に接続してください。
- 動的にスポーンした場合、ノードがツリーに追加されて
_readyが実行された後に、複製ノードごとのシグナルが(スポーン元とリモートのピア両方、かつルートとサブオブジェクトの両方で)発火します。 - 登録済みシーン(
register_current_scene()またはload_scene()経由)の一部として複製ノードがロードされた場合、シーンがツリーに追加されて、シーンのマップに属するすべての複製ノードのバインディングが完了するまで、シグナルの発火は遅延されます。同階層の複製ノードは、コールバックからアクセスできることが保証されます。
サブオブジェクト
サブオブジェクトは、スポーンしたルートにアタッチされた動的な子オブジェクトで、個別の同期バッファを持ちます。これらはルートの権限を共有していて、親オブジェクトとサブオブジェクトの両方を同じクライアントが所有します。
サブオブジェクトをスポーンするには、スポーンされるシーンの子ノードにFusionSpawnerを追加してサブスポーンモードに切り替えます。
- インスペクター上から(推奨):
FusionSpawnerのSpawn As Sub Objectを有効にします。_ready時に、FusionSpawnerは祖先をさかのぼり、最も近い兄弟の複製ノードを見つけてバインドします。 - コードから:明示的に
bind_root_replicator(replicator)を呼び出して、バインドしたい特定の複製ノードを指定します。
どちらの方法でも、FusionSpawnerのspawn()呼び出しが、ルートオブジェクトではなくサブオブジェクトを生成するようになります。ただし、複製ノードの下にFusionSpawnerを配置しただけでは、自動的に変換されないため、明示的な設定が必要です。
GDScript
# スポーンされたシーンのスクリプト内:
const TurretScene = preload("res://turret.tscn")
@onready var sub_spawner: FusionSpawner = $SubSpawner
func _ready():
sub_spawner.add_spawnable_scene(TurretScene)
sub_spawner.bind_root_replicator(get_node("FusionSharedReplicator")) # クライアントサーバー型なら"FusionServerReplicator"
func spawn_turret():
var turret = sub_spawner.spawn(TurretScene)
turret.position = Vector2(0, -20)
サブオブジェクト自身も複製ノードを持つ必要があります。
サブオブジェクトに独立した権限を持たせることはできません。
所有権は常にルートオブジェクトに従います。