Spawn 2D bullet and sync for Multiplayer

166 Views Asked by At

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.)

2

There are 2 best solutions below

8
MeSteve95 On BEST ANSWER

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).
1
MeSteve95 On

One thing I just noticed is that you never set the position of the instantiated bullet, so it may be that your bullets are spawning at the world origin and that's why you're not seeing them.

One way that I like to solve this is to create a Marker2D node and move it to the end of the gun/whatever you're using to shoot. Then in your Player script you get a reference to this Marker2D, and after instantiating the bullet, you call:

bullet.global_position = bullet_spawn_marker.global_position