Open Shadowblitz16 opened 2 years ago
But I don't have any documentation on how it works and I am assuming the scene that is spawned is random based on the fact that there doesn't seem to be a way to spawn it based on network id.
If you use automatic spawning, the spawned scene is the one you add to SceneTree from the authority. So if you configure the autospawn list as ["res://one.tscn", "res://two.tscn"]
, and assuming the spawner target (spawn_node) is $Objects
, then:
var one : Node = load("res://one.tscn").instatiate()
$Objects.add_child(one) # Will spawn scene "one.tscn" on clients
var two : Node = load("res://two.tscn").instatiate()
$Objects.add_child(two) # Will spawn scene "two.tscn" on clients
var three : Node = load("res://three.tscn").instatiate()
$Objects.add_child(three) # Will not spawn anything remotely since "res://three.tscn" is not in the list.
I suggest instead of it taking a scene it takes a spawn parameter resource which allows us to supply a transform range and a scene to spawn per range.
Note that this kind of custom behaviors can already be achieved using custom spawning.
You can implement MultiplayerSpawner._spawn_custom
and then use MultiplayerSpawner.spawn(data)
to spawn different scenes depending on the provided data
.
There are multiple ways to implement what you want specifically. An approach I can suggest is something like:
extends MultiplayerSpawner
@export var min_position : Vector3
@export var min_rotation : Vector3
@export var min_scale : Vector3
@export var max_position : Vector3
@export var max_rotation : Vector3
@export var max_scale : Vector3
func _spawn_custom(data):
if typeof(data) != TYPE_INT:
return null # Invalid spawn requested.
var id : int = data
# Use id to instantiate the desired scene
var node : Node = load("res://player_%d.tscn" % id).instantiate()
# Apply initial values if we are the authority
if is_multiplayer_authority():
node.position = Vector3(randf(), randf(), randf()) * (max_position - min_position) + min_position
node.rotation = Vector3(randf(), randf(), randf()) * (max_rotation - min_rotation) + min_rotation
node.scale = Vector3(randf(), randf(), randf()) * (max_scale - min_scale) + min_scale
return node
Then have a MultiplayerSynchronizer
in the player scenes configured to replicate at least position
, rotation
, and scale
on spawn (possibly also on sync depending on the game specifics).
You can finally spawn from the authority by calling:
if $PlayerSpawner.is_multiplayer_authority():
$PlayerSpawner.spawn(player_id)
And this will also allow clients to connect mid-game (which will automatically spawn existing players with the proper transform) applied.
Describe the project you are working on
A arcade spaceship war game
Describe the problem or limitation you are having in your project
In my game spaceships spawn in different locations depending on what player it is. However I would like to use the spawner to spawn players manually on the server which also syncs them on the clients.
Right now I am using 4 scenes with separately positioned player node for each network id. But I don't have any documentation on how it works and I am assuming the scene that is spawned is random based on the fact that there doesn't seem to be a way to spawn it based on network id.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
I suggest instead of it taking a scene it takes a spawn parameter resource which allows us to supply a transform range and a scene to spawn per range.
I also suggest that the spawner automatically and manually selects the spawn parameter based on network id.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
spawn parameter resource would basicly be a...
the manual api for spawning things would be..
If this enhancement will not be used often, can it be worked around with a few lines of script?
It would be used more then the current version.
Is there a reason why this should be core and not an add-on in the asset library?
Its part of core already.