Let's talk about netcode
Recently I've started playing around with Godot. So far I got a basic "walker" type of game logic, so I decided to go for adding multiplayer support. And that got me thinking: what is really the best way to do exactly that?
Most multiplayer solutions just update entities' positions across multiple clients. Older ones such as Doom just sends player commands, so the client does the simulation and updates positions based on commands. And there is probably something else that I left out.
I thought I'd open this topic up for discussion.
89 Replies
I dont know if im explaining this well enough, but im going to go ahead and try.
This is probably very inefficient, but i would go along the lines of something like the game is stored as an object (im going to visualize it with JSON)
say you have the following game
this needs to be kept up to date between all players
now saw player one moves in a direction 3 units
in this example, on the x axis
instead of resending the new object in full, check what changed and only send what changed
so instead of sending
this to all the players, send this
and then merge game (the data the players currently have on their local device) with update (the new data the server just sent)
this is bound to have its issues, but for someone who has never actually looked into how online gaming data sending works, id say this is a pretty good idea
@polyzium
Quake 3 uses the same pattern here
I mean that would make total sense to only update what has changed but for compiled languages this may pose a problem if you unmarshal the data into a struct.
position.x is the only value updated, then what's position.y? Zero? That's UB right here
can you not merge objects in go? for example
Nah it's not in Go
oh wait
i misunderstood you said godot i thought go
In JS this could be done nicely with things like Object.assign, dunno about other languages, never did C#
Currently using GDScript for prototyping, which is loosely based on Python
But I'm sure I'll figure something out
Anyways, another problem to tackle is: does the server do the gamesim and send the player positions, or should that be relied on clients? The latter would take some load off, but would introduce vulnerability to hacks.
I believe that's what Minecraft does.
Like you said this makes hacking really easy. Though this is what most people do, though it does (like you said) make your code vulnerable. I’m not sure how powerful your server is going to be. So I’m not sure dealing with everything on the server will work good.
There will probably be quite a bit of latency
There will always be latency
but can be mitigated with interpolation, sort of
Of course latency is always a problem but doing all player movement and physics on the server will be worse
Worse in what sense? Latency?
Yes. Doing all physics on the server would result in more latency for the players.
Well GMod multiplayer somehow does work with all of that, I haven't looked how exactly does it work but it somehow does
It may work, I’m pretty sure games do this. Though most of the time for this to succeed you need a good powerful server
Calculating basic movement and physics isn’t very hard to do. When you start adding more physics based things (wether that be a prop or similar) to your game your only adding more work for the server
That is a call for stress testing
Yes. I do think this method is best for avoiding cheaters to some degree. It should stop any movement based cheats
Though I think doing the physics for 10 or so players at the same time may cause latency issues. More so if you were just to do movement on the client side
How more if it's on client?
Not more latency on the client. When I said that I was referring to the “doing physics on the server” method.
When I said “more so” I was just trying to shorten saying. “you’ll end up having more latency dealing with physics on the server, more so then if you were just to do physics on the client.”
If that makes any more sense
Oh I get what you mean now
< fluent in Broken English
That’s fine lol
I understand as English isn’t your first language I presume
I thought you already knew that?
Well I know your Russian though I wasn’t fully sure, 90% sure English wasn’t your first language
I mean that's true but surprisingly you got confident in this fact only now lol
anyways
Doing clientside physics may introduce desync issues between players
so one player sees another player in a totally different place than where they should be
How so? If done right I don’t see how it could. Unless the player has a bad pc and can’t do physics
GUess what, that's the same scheme GZDoom follows
If the player has a low spec machine it will lag the crap out of you and others
because opthers have to wait til the other player unlags
I don’t think desync will be that huge of an issue. I mean in games when people are lagging the jump all over the place
That’s just life using this method
I’m games where this method is used when people lag they teleport and such
Not sure how good of an option this is but, I guess you could just do physics on the client for the player. Then send their position to the server, and forward that data to all players
So even when lagging this shouldn’t be hard on other users
And it may create that “teleporting” effect when people are lagging
Like I said, this can be mitigated with interpolation.
Interpolation of what?
The player's position.
Interpolation to me is that wacky string that lets you have placeholders. Please elaborate
So instead of teleporting 0.5m-1m away from their previous point, they will move smoothly between them, and the travel time is their ping.
So if their ping is 200ms
Instead of teleporting several centimetres away from their previous position to a new one after 200ms
Ah
The player will move smoothly between them during these 200ms
Linear interpolation
In mathematics, linear interpolation is a method of curve fitting using linear polynomials to construct new data points within the range of a discrete set of known data points.
I see. Well try it out I guess. I still don’t think dealing physics on the server is a bad idea. Though I think latency will only grow and exponentially quick depending on the number of players
I think this method is ok but I don’t do server stuff with games
Have you tried searching up what most games do for multiplayer?
If you're making a competitive game, this is critical, but for anything else it'll do
Actually I think most games use it so the server does not get loaded
it's a performance saving measure after all
Yeah
Godot has something called
rpc_unreliable
which sends player commands over UDP if I'm not mistaken.
Most tutorials use that but I want to go for a different approachlol “unreliable”
If you think about it, it makes sense because UDP is an unreliable protocol.
Not unreliable in sense "it crashes/it performs like shit" etc
In sense that the packets don't have to reach the end destination
Oh, that’s not good
If you're updating player positions, UDP is good
If you get a temporary packet loss in TCP, you'll receive a big batch of player position updates (when the connection comes back up obviously) that become redundant after, and only the latest packet is accounted
If you get the same with UDP, you'll receive only the last packet.
only that and everything that comes after obviously
Ah, so UDP is much better for player movement and physics
My explanation might be oversimplified, but in general, yes.
For stuffs like data transfer, player commands, anything that HAS to be received by the client, go for TCP instead.
There is also Valve's GNS. https://github.com/ValveSoftware/GameNetworkingSockets
GitHub
GitHub - ValveSoftware/GameNetworkingSockets: Reliable & unreliable...
Reliable & unreliable messages over UDP. Robust message fragmentation & reassembly. P2P networking / NAT traversal. Encryption. - GitHub - ValveSoftware/GameNetworkingSockets: Re...
This is just a wrapper around TCP/UDP with both reliable and unreliable messaging features. It can also exceed the regular TCP/UDP packet size.
Valve devs got some big brain people down there
I'm struggling with English today pls help
Anyway, there is also the C# bindings, which could integrate well with Godot's C# language support.
I’ve never played with anything but GDScript. Using libraries is possible with C# and Godot?
I guess so, if Godot allows C# and GDNative with it as well.
There are also bindings for Lua, Python, Rust, etc. for Godot, so go wild.
@earth's bird I'll try implementing multiplayer right now
Alright, best of luck
Well well well first problem I encountered is that my player controller is entirely hardcoded to be interacted with a keyboard and a mouse
I could go two ways. First one is to create one player class for everything and then "posess" it using a keyboard and a mouse
Or create a special networked player class for network players only
Ugh
Godot networking is so confusing
Making multiplayer in general is
Why is RPC for multiplayer even a freaking thing
¯\_(ツ)_/¯
That is a security vulnerability
Why don't you just watch a tutorial? It's probably the easier route
Also, the
rpc()
function does what? Sends? To who? Everyone?
This is the reason I'd prefer to use raw sockets or a mid-level abstraction thereof
so I have full flexibilityI see
I'm pretty sure Godot has mid-level abstraction
Does it not?
Godot Engine documentation
High-level multiplayer
High-level vs low-level API: The following explains the differences of high- and low-level networking in Godot as well as some fundamentals. If you want to jump in head-first and add networking to ...
I found this https://github.com/PerduGames/gdnet3
GitHub
GitHub - perdugames/gdnet3: An ENet wrapper for Godot 3.
An ENet wrapper for Godot 3. Contribute to perdugames/gdnet3 development by creating an account on GitHub.
Does exactly what I need
OK wtf is wrong with me
If I'm going to use JSON then how would Godot serialize stuff like Vector3??
Why am I getting my theoretical knowledge fully ready before doing it in practice
PSA: Godot cannot serialize classes
I'm pretty sure it can actually
Until I realized I was trying to replicate the Go's messaging workflow in GDScript
which totally won't work as GDScript classes have no "tags" compared to Go structs
so the marshaler does not understand how to name that class field
and instead returns a generic object
think of it as an JS
[object Object]
So I assumed you've already resolved this issue?
No
Still searching for an elegant netcode solution
Not 100% sure if this helps in any shape or form, but here you go
Godot Engine documentation
Saving games
Introduction: Save games can be complicated. For example, it may be desirable to store information from multiple objects across multiple levels. Advanced save game systems should allow for addition...
I have so many questions in regards to futureproofing
what if I wanted to do delta compression, or VoIP
I don't see how (if you are) saving the state of a player relates to VoIP; a voice transmission protocol. For delta compression I'd have to look into, as to be quite frank I've never heard of it
Delta compression is basically sending only what has changed against a previous game state
previous game state that a player has received, that is
That's the same pattern Quake 3 uses
As for VoIP, this might pose a big problem cuz if I were to do communications over one connection then uhh
jeez this is so confusing
Then I'm not sure what would be the issue? With Godot's example they say you can use functions like
to_json()
and parse_json()
. Instead just return a JSON of what has changed against a previous game stateProblem is
Godot cannot serialize classes in the same way Go serializes structs
Well they're two different things
both
to_json()
and JSON.print()
return the same value
And instead you have to make some sort of a dict wrapper
like described in docsYes
So that's a major issue foir productivity
define. everything. manually.
You may benefit from joining the Godot Discord server. I can send you an invite if you'd like
I spoke with them, TLDR in GDScript it requires generating a dict, and doing that requires some half-assed ways of doing that
Honestly I'm better off going the C# or Go bindings route
I see
You may be.
@polyzium is there no equivalant of JSON.stringify?
JSON.print but the classes in GDScript are half assed when it comes to serialization
thats stupid
Indeed it is, that's why you'd better resort to C# or Go.
I might even pick up Rust some day
just hope that it doesn't melt my brains again
C# still leaves me with a feeling of disgust, because, first of all, it's Java but worse, and second, Microsoft
Not everything Microsoft tends to be bad but I agree C# is bad
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Still, Microsoft
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Even if it is you'd still be dependent on nuget
At least java is more open
Both have classes
Both use bytecodes
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View