Everything a normal rollback implementation does, is what i do. Aslong as you can keep a full record of what the game state is each frame you can do the same
Hey, I was just wondering how you managed to achieve this with Roblox’s server authoritative structure?
Simple, just dont use it
Each client gets instructed to make their local map and character models, i do all my networking logic trough unreliable remote events. Since everything of the game only exists locally,i dont have to worry about replication messing things up
Do you mind if I message you my current situation regarding implementing this to get further support?
Sure, go ahead (chars)
On here or any other platform? (Disc, Guilded, or wtv)
Anything works, my discord is slug_slugger
Alr Imma add you my disc is indojunnie
Do you happen to have this released like a small uncopyprotected project demo? I plan to implement this
Don’t know why i didn’t get a notification of this, sorry, but no i won’t be making a demo place, as a functional version of it would mean having to dump a massive amount of my game’s internals out there for everyone to take, lol.
but do take a look at these
Also nice to know, about a week ago, i held the first playtest of the game with the netcode
Players seemed very content with the experience, so i really recommend that more developers take on this system
i had no idea you got diaphone to join the playtest… thats a crazy achievement
let alone the fact that you were able to get the netcode working this smoothly
I made an uncopylocked Rollback test with all the scripts inside if you are curious.
0F input delay on 150ms
Also the rcmagic github user actually has a full YT tutorial on this topic. (I simply translated his C++ to LUA).
cool stuff man! hopefully these different approaches to fighting game netcode will become more popular within in the roblox space
also, i did decide to (slightly) change to alter the networking model. I’ve changed my stance a little on what is the best to do given the way roblox is structured
Rollback in itself remains in my game, but instead of clients communicating with eachother, they now exclusively communicate with the server that acts as the source of truth over what inputs are being ran. the clients plays all the inputs the server gives (even local input) and will sync their game’s frame to what the server is at. the server can also fill in a player’s inputs with it’s own prediction in case the player doesnt report their inputs to the server on time, so that the match can go on and doesnt have to netpause for the other player.
This networking model is essentially what you will find in 2XKO and Rivals of Aether 2. But best explained by Rocket League (GDC Talk)
If you are interested in implementing rollback into your games, I think taking advantage of your server is important as it adds stability to your netplay compared to the fragile “direct” player > server > player approach. Atleast, this is what i deducted after having 2 public playtests with the netcode
This is a bit confusing so I have 2 main questions
-
Is the game simulation still handled by the clients only or does the server also run its own clone of the game
-
What’s the difference in the end result (does it eliminate foul play, reduce lag)
the server only hosts what the final inputs will be that each client will run, it does not run actual game logic, this is still done by the clients
the previous solution i was running relied on both players having a good connection for the game to run smoothly, if one player was having network issues, even the player with a good connection would immediately feel it on their side. by using the server as the source of truth, it can fill in gaps of inputs that one side may fail to provide, the player thats lagging will immediately sync to the server when it can and catch back up to speed, while the other player doesnt even notice that something happened, since the server provided the filled in inputs
“What’s the difference in the end result (does it eliminate foul play, reduce lag)”
tldr, you’re not affected by the lag of your opponent anymore, the latency is about the same.
Is there any pseudocode for how you handle this now compared to your original input syncronization?
The way I have been interpreting what this means has been
--server side
local serverFrame: number
local remoteFrames: {[Player]: number}
function update_server()
local isUpdated = true
for player, frame in remoteFrames do
if frame <= serverFrame then
isUpdated = false
end
end
if isUpdated then
sendLatestInputs()
end
end
But this feels more like a hybrid between rollback and lockstep and I feel like would lead to more rollbacks than desired