windows2dgodotmultiplayergdscript

Spawn 2D bullet and sync for Multiplayer


I am trying to spawn bullets from the Player, the bullet spawning works right, but I cannot figure out how to network it. I tried spawning it as a sibling and child of the Player, but I cannot get it to show up across all clients.

Player script:

extends CharacterBody2D

var health = 10

func _enter_tree():
    set_multiplayer_authority(str(name).to_int())
    
@onready var camera = %Camera2D
const SPEED = 330.0
const JUMP_VELOCITY = -400.0

# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")


func _physics_process(delta):
    if not is_multiplayer_authority(): camera.enabled = false
    if is_multiplayer_authority(): 
        if Input.is_action_pressed("use_shoot"):
            shoot()
        
    #if not is_multiplayer_authority(): return
    # Add the gravity.
    if not is_on_floor():
        velocity.y += gravity * delta

    # Handle jump.
    if is_multiplayer_authority(): 
        if Input.is_action_pressed("i_up") and is_on_floor():
            velocity.y = JUMP_VELOCITY

    # Get the input direction and handle the movement/deceleration.
    # As good practice, you should replace UI actions with custom gameplay actions.
        var direction = Input.get_axis("i_left", "i_right")
        if direction:
            velocity.x = direction * SPEED
        else:
            velocity.x = move_toward(velocity.x, 0, SPEED)
        move_and_slide()
                    
func take_damage(amount):
    print("YOUCH")
    print("YOUCH")
    health -= amount
    if health <= 0:
        queue_free()
        
@rpc()
func shoot():
    var bullet = preload("res://scenes/bullet.tscn").instantiate()
    add_child(bullet)
    bullet.rotation = bullet.global_position.angle_to_point(get_global_mouse_position())
    bullet.rotation_degrees += -90


func _on_area_2d_body_entered(body):
    if body.is_in_group("Arbullet"):
        queue_free()

Bullet script:

extends Area2D

var speed = -560
# Called when the node enters the scene tree for the first time.
func _ready():
    pass # Replace with function body.


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
    position += transform.x * speed * delta


func _on_body_entered(_body):
    #if body.is_in_group("player"):
        #body.take_damage(1)
    #queue_free()
    pass

I cannot figure out a reasonable way to spawn the bullets without damaging the player.

How the spawning the bullet looks from the player:

Player shooting bullet

Bullet facing wrong way (No errors)

Spawner screenshot

Console errors

This is if I try to add synchronizers, and they still do not work, I have made sure to sync position and rotation, thanks.

(I think all the errors exist because I can't spawn the bullet outside of the player scene.)


Solution

  • In order for an instantiated scene to be shared across the network, those scenes need to be added to a MultiplayerSpawner node.

    In your case, this is as simple as

    1. Add a MultiplayerSpawner node to your game scene.
    2. Add your bullet scene to the AutoSpawnList of the MultiplayerSpawner.
    3. Set the MultiplayerSpawner's SpawnPath variable to the node that will be the parent of the spawned scenes (the node that you call add_child() on after spawning the bullet).