Instantiated RigidBody3D Projectile Syncing Issues

Godot Version

4.4.1

Question/Background

Working on a throwable projectile for my 3D multiplayer (P2P) game, in which the player (a CharacterBody3D) instantiates the projectile and applies an impulse to it when the throw button is pressed.

On both host and clients, the projectile spawns, is shown flying through the air, and can do damage, however only the host can change the angle (up/down) at which they throw and have that resulting projectile flight path sync across all players. Clients can inconsistently throw at various angles, however the “altitude” of these more angled throws (for example if the player looks straight up) does not sync like the host’s throws do. Instead, the other players just see the projectile go directly forward. Additionally, the clients seem to be unable to throw projectiles at any angle other than directly forward the majority of the time.

The script of the projectile itself (a coconut) only has the player damage logic, so I haven’t included that. It’s a rigidbody3D with a multiplayer synchronizer that tracks the linear + angular velocities, and position + rotation of the rigidbody3D node. Screenshot of projectile (coconut) scene below:

I’ve seen other posts mention using the MultiplayerSpawner node (vs instantiating through an rpc like I’ve been doing), as well as the _integrate_forces function, but I’m not sure if my lack of those things is the problem.

Any comments or resources are appreciated. The relevant parts of my player script are included here:

player.gd (simplified):

  @onready var camtpv = $camroot/h/v/ThirdPersonCam
  var Coconut = preload("res://Scenes/Objects/Weapons/coconut.tscn")

  if is_multiplayer_authority(): 
     if Input.is_action_just_pressed("throw") and canThrow:		
        yeet.rpc()

  @rpc("call_local")
  func yeet(): 
	playback.travel(attack2_node_name) #play throw animation
	var coconut_ins = Coconut.instantiate()  #spawn coconut
	coconut_ins.position = $CavemanMain/Armature/ThrowSpawnLocation.global_position  #spawns at marker3D placed at hand of character model
	get_tree().current_scene.add_child(coconut_ins) #adds instantiated coconut as child of Level scene, NOT of the player

	var ForceMagnitude = 80  #throw force 
	var CameraDirection = -camtpv.get_global_transform().basis.z    #throw direction
	coconut_ins.apply_central_impulse(CameraDirection * ForceMagnitude)