How to use right spawn_function in MultiplayerSpawner?

I don’t know why I decided to do it with this method, maybe just wanted to practise… than I realized that it’s not the best method and Nathan’s method better, but I got error messages in the client instance:

I have:

  1. A Chest scene, that creates a Key if Player’s interact with it


    There’re MultiplayerSync node that synchronize is_locked variable (you’ll see it later)

  2. A Key scene, which has nothing except Visuals

  3. Interactable scene, which is an Area2D and the child of Chest scene

I guess there is no problem with with my Interactable scene, but want to show it, because it’s a part of creating key:

class_name Interactable
extends Area2D  # interactable.gd

signal interacted

@rpc("any_peer", "reliable", "call_local")
func interact():
	if !multiplayer.multiplayer_peer:
		return
	if !multiplayer.is_server():
		return
	
	interacted.emit()

And the main code, on_interactable_interacted() function 100% could be called, because I got errors, it means that issue not with interacting, not with Areas (Player’s interaction):

extends Node2D  # chest.gd

@export var key_scene: PackedScene  # There're Key scene (I've checked, I putted it in)

@onready var interactable: Interactable = $Interactable
@onready var key_spawner: MultiplayerSpawner = $KeySpawner
@onready var synchronizer: MultiplayerSynchronizer = $MultiplayerSynchronizer

var is_locked := true


func _ready() -> void:
	key_spawner.spawn_function = spawn_key
	synchronizer.delta_synchronized.connect(on_synchronizer_delta_synchronized)

	if !multiplayer.multiplayer_peer:
		return
	if !multiplayer.is_server():
		return

	interactable.interacted.connect(on_interactable_interacted)  # it should be called only in the host instance, than it will be synchronized in clients


func update_chest_state():
	is_locked = false
	set_chest_state()


func set_chest_state():
	chest_locked.visible = is_locked
	chest_unlocked.visible = !is_locked


func spawn_key() -> Node2D:
	var key = key_scene.instantiate()
	key.position = key_spawn_position.position  # I realized that it's unnecessary, because MultiplayerSpawner (KeySpawner) could do it
	return key


func on_interactable_interacted():
	if is_locked:
		update_chest_state()
		key_spawner.spawn()


func on_synchronizer_delta_synchronized(): # only is_locked variable sync's
	set_chest_state()

Yeah, this is bad code, I will delete spawn_key func and redo it, but how to fix it?)

Oh, forgot to say: in the host instance I also don’t see key instance (but there’re no errors)

Just some ideas:

  • move “key_spawner.spawn_function = spawn_key” to _enter_tree instead of _ready (like in level.gd)
  • comment out the two ifs in _ready (not sure they are needed since we check for is_server in interactable.gd)
  • disconnect the two signals (cleanup) in _exit_tree (like in level.gd)
1 Like

Hello~
I also dodged to using the custom spawning of the Multiplayer spawner because I ran into issues with the add_child() approach. Some googling (and finally this solution by @camjknight HERE :white_heart: ) led me down into using the custom spawn, but that also clicks better with my brain for some reason, to be honest.

Anyways, @AntiVirusJ I found that passing a parameter with spawn() solved the errors for me.
You don’t have to actually use it and can hide it behind an _underscore

Example:

func _tree_enter()
  spawner.spawn_function = spawn_thing

func spawn_thing(_x):
  return thing_scene.instantiate()

func _on_interaction():
  spawner.spawn(1)
2 Likes

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms