スポーン
シングルプレイヤーでは、シーンをインスタンス化するとローカルノードが作成されます。マルチプレイヤーでは、同様の操作ですべてのクライアント上にノードを作成し、レプリケーションシステムが追跡できるネットワーク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 and Despawn
ネットワークオブジェクトを作成するにはspawn()を呼び出します。すべてのクライアント上から削除するにはdespawn()を呼び出します。
GDScript
# 最初に登録されたシーンをスポーンする
var player = spawner.spawn()
player.position = Vector2(100, 200)
# 特定の登録されたシーンをスポーンする
var projectile = spawner.spawn(ProjectileScene)
# デスポーンする
spawner.despawn(player)
スポーン後にノードのプロパティを設定してください。複製対象のプロパティ(FusionReplicationConfigで設定)は次回のネットワーク更新に含まれます。
シーン構造
一般的なゲームシーンにはゲームロジックとFusionSpawnerが含まれており、スポーンできる各シーンにはルートノードの子ノードにFusionReplicatorが含まれています。


プロパティ
以下のプロパティでは、スポーンしたオブジェクトがツリーのどこに配置されるか・どのシーンが利用可能かを設定できます。
spawn_path(NodePath,"..") - スポーンするオブジェクトの親spawnable_scenes(Array[PackedScene]) - 登録されたスポーン可能なシーン
シグナル
FusionSpawnerは、すべてのクライアント上でオブジェクトが作成/破棄された際にシグナルを発火します。
spawned(node: Node)- オブジェクトがスポーンした(ローカル/リモート)despawned(node: Node)- オブジェクトがデスポーンした
サブオブジェクト
サブオブジェクトは、スポーンしたルートにアタッチされた動的な子オブジェクトで、個別の同期バッファを持ちます。これらはルートの権限を共有していて、親オブジェクトとサブオブジェクトの両方を同じクライアントが所有します。
サブオブジェクトをスポーンするには、スポーンされたシーンの子ノードとしてFusionSpawnerを追加し、bind_root_replicator()を呼び出して親のFusionReplicatorにリンクさせます。これによって、このFusionSpanwerは「サブスポーナー」となり、spawn()呼び出しによってルートオブジェクトではなくサブオブジェクトを生成するようになります。
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($FusionReplicator)
func spawn_turret():
var turret = sub_spawner.spawn(TurretScene)
turret.position = Vector2(0, -20)
サブオブジェクト自身もFusionReplicatorを持つ必要があります。
サブオブジェクトに独立した権限を持たせることはできません。
所有権は常にルートオブジェクトに従います。