godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
88.64k stars 20.1k forks source link

MultiplayerSpawner doesn't despawn scene ("non-dynamic") nodes #74327

Open sfreed141 opened 1 year ago

sfreed141 commented 1 year ago

Godot version

4.0.stable.mono.official

System information

Windows 11

Issue description

If the spawn path for a MultiplayerSpawner contains nodes they won't be despawned on other peers. Maybe I'm not understanding exactly how the spawner works but this makes it awkward to create levels with nodes that will eventually be removed (eg collectibles, enemies, etc). image For example with SphereSpawner.spawn_path set to Objects those two spheres won't despawn when freed on the authority.

The despawning works fine if you create the nodes dynamically (eg instantiate the node and add_child on the spawn path)

Steps to reproduce

Open the sample project, set Debug | Run Multiple Instances to 2, and start debugging. Click Host on one window and Connect on the other. Ensure the bouncing spheres are visible in both windows, focus the host's window, and press the "ui_end" key. You'll see the spheres are freed on the host but not despawned on the client.

Minimal reproduction project

spawner-repro.zip This is the sample project from https://godotengine.org/article/multiplayer-in-godot-4-0-scene-replication with 2 modifications:

  1. Added script to sphere to queue_free() when multiplayer authority presses "ui_end"
  2. Added a MultiplayerSpawner to level.tscn with SpawnPath set to Objects
lolomap commented 9 months ago

My MultiplayerSpawner does not despawn even dynamicly added nodes on 4.1.2 Mono. (I use custom spawn_function)

golxzn commented 5 months ago

I have the same problem. Any changes?

golxzn commented 5 months ago

For those suffering:

Create the temporary items container Items_buffer: image

Attach this script to the buffer and select the target node, which is in spawner's spawn_path:

class_name ChildrenMover extends Node

@export var target_node: Node

func _ready() -> void:
    if multiplayer.is_server() and target_node:
        for child in get_children():
            remove_child(child)
            target_node.add_child(child)

    queue_free.call_deferred()