Godot movement of bullets in multiplayer game using replication

Godot Version

4.3

Question

Hey, I have some issues around Godot’s multiplayer solution and how it works. My project right now is a P2P game with WebRTC and it’s using Godot replication. Everything was good until I tried to spawn a bullet. I wasn’t having any issues with creating the bullets, but the bullets themselves. Their movement is so jittery and I’m not sure why. I tried multiple approaches. Initially the bullets were assigned in the player hierarchy, so I moved them to be more higher level (didn’t help). I tried multiple approaches with MultiplayerSpawner and Synchronizer (same effect). I feel like the approach to create multiplayer games in Godot is so clumsy, but maybe I’ll get used to it. I’m sending screenshots and video of the issue, so you’ll know what I’m struggling with. Thanks in advance for the help.

Video: https://youtu.be/4F0Z4E8mwFE
Zrzut ekranu 2024-09-06 173352
Zrzut ekranu 2024-09-06 173431


The screens represent:

  • Game scene hierarchy
  • Player hierarchy
  • Code for Bullet
  • Code for Player

Please take the components used and details of the code with the grain of salt as I was changing them several times, just take them as a rough idea where I’m currently.

This is not Godot’s fault as far as I know, but the consequence of networking.

I will presume you are updating only the position and not velocity? I assume the authority is updating position with a velocity at 60fps and the peer is only getting snapshots at maybe 60fps or less, and no velocity. The network could add jitter and packets could come out of order. Unless you are using reliable which is never a good idea for fast game state updating.

Checkout my physics based syncher with a ring buffer.

1 Like

I would also definitely read up on network games.

I really like this article series. it focuses on physics, but even if this isn’t a physics based game the same fundamentals will apply.

1 Like

Hey @pennyloafers :wave:
Thanks for the help. I would say I’m pretty good at networking, but not that great at Godot and this is where I’m struggling. Your solution looks good, but It feels too complex for what Godot is capable of (I think). With replication you should be able to just slap MultiplayerSynchronizer onto an object, figure out where the object should be simulated and that’s it. The interesting part of this issue is that in one of my attempts I was printing velocity and direction of the ball and it was constant every frame (and It was fully simulated localy; no multiplayer, replication, etc.).

I will presume you are updating only the position and not velocity?

Fair, the code was hidden behind velocity_component, but let’s assume the bullet code does this:

extends CharacterBody2D

@export var direction: Vector2;

func _physics_process(delta: float) -> void:
	velocity = direction * 20
	move_and_slide()

I created a test project without networking and it worked correctly (meaning the issue lays mainly in some kind of networking/replication issue on my side). I also checked a few resources on Godot replication (not much is out there) and this demo project - Multiplayer in Godot 4.0: Scene Replication shows that you can have an object (Sphere) that is just there with MultiSynchronizer without any additional code for it to work. Just checked and it did work. I added a script like above to the sphere and it worked… Meh, I think I’ll just redo the project. It’s not that big and I could clean some of the stuff there. Could you only explain me why the addtional state saving and interpolation is needed when Godot theoretically does it for you with replication ? Thanks in advance, and thank you for your answer because gave me a little push to explore the issue further and make some progress.

You can definitely get a smooth replication by updating position alone on local host pretty easy, just need position updating once per frame at a high frame rate. (but by itself will never be acceptable for real network play. Syncing velocities helps accuracy. Syncing accelerations makes it better, but harder to predict)

What does your multiplayer synchronizer replication config look like? What properties are being synchronized and what is the replication time? This was never shown.

When I mentioned updating position and velocity, I meant synchronizing. The authority of the object needs to send position and velocities in the synching state.

The velocity then needs to be acted upon by the remote instance body. Which it seems like your character body should if they share the same script.

I have never used a character body yet, in multiplayer, to know if there are quirks like for rigid bodies (Since network packets are handled outside the physics server, there could be conflicts with who is trying to set position on the node.).

I use many spawners and synchronizers with only one RPC function, so far, to trigger a spawn of a player in my own project. Most of the time it is butter smooth even from a coffee shop down the road, there are some strange edge cases at times but I haven’t gotten to debug it yet.

Considering my code and Godot, Godot multiplayer API and the multiplayer nodes, do the absolute minimum. There are implications for rigid bodies node position and how the physics server works. This could be true for character bodies too, as move and slide does interact with the physics server if I can recall correctly. There could even be a whole slew of issues outside of Godot since we are sending information between different processes.

1 Like