Advertisement

Multiplayer Client-Server: Need 4 Advices

Started by January 12, 2024 04:16 PM
5 comments, last by Synthesizer 10 months ago

Hello everyone!

Background:
I've been working on a fighting game project for a few years now, but due to switching engines I've faced the challenge of migrating / restarting.

I've written a Client - Server logic where client executes (predicts) and sends “new player” and “controller status” messages to the server. The server processes the messages and broadcasts the results ("add user" and “final positions”). When clients receives the messages from the server they set other's values or check if the predictions were right, and otherwise reconciliate.
All that was relatively fine.

Now:
When reimplementing, I decided to create a character selection screen before jumping into gameplay. There's where I found that if I want to really do it the “client-server” way, I should be sending the “controller status”, and the server should be broadcasting each cursor position, status, character selection, screen item enable/disable, etc. etc. Otherwise, I would here (it's just a character selection screen after all) just cheat and the server would forward the “controller status” so the clients process it like if it were locally.

Still some questions came to me:

1) Should the server always broadcast the full scene status? (characters' positions, orientation, health, actions, powers acquired / ready to use, etc.) I have seen tutorials where they broadcast only upon “controller status” reception, but when having NPCs, time / logic triggers, then you should as well broadcast. So is it worth it to be selective for all these cases, or just broadcast always?

2) Defining messages types to send back and forth info ends up being really bad for design and flexibility. I feel like I'm totally constrained and one would end up whether using one message for all (repurposing the fields) of defining a million different message types ("cursor redraw", “character redraw”, “whatever event", “player won”, “player changed armor”, “player changed weapon”, etc.) Any advice here?

3) Server can broadcast final positions for the client to put the characters where the server says. I thought of including the “action” as well (attack, jump, etc.) But when the client receives the “action”, the client has to process it (needs to play the animation, show particles, effects, sounds, etc.) Is this a correct approach? Should I also consider anything else vital that I'm not seeing at the moment?

THANKS A LOT!

This is not a Game Design question (it did not belong in the Game Design forum). What is Game Design?

Thread is now in a more appropriate forum.

-- Tom Sloper -- sloperama.com

Advertisement

Synthesizer said:
I should be sending the “controller status”, and the server should be broadcasting each cursor position, status, character selection, screen item enable/disable, etc. etc

I don't see why it needs to do this. What the server should receive, and broadcast, is whatever you're comfortable making client authoritative for. For a fighting game, typically this is the acutal-inputs, including which frames they're input at, to properly calculate timing of attacks/defenses/combos.

But, for character select, at least “street fighter” style, you just need to send “this is my currently chosen character” and “now I lock in my choice.” This lets every other player see the highlight frame around what character you're selecting, and once you lock in the character, it lets the server progress you (and others) to the next screen, once all characters are locked in. (There may be additional requirements, like unlocking someone if anybody else changes their selection after the lock, for example, depending on how you want this to work.)

enum Bool { True, False, FileNotFound };

Hello hplus0603,

Thank you for your answer.

hplus0603 said:
whatever you're comfortable making client authoritative for

Yes, I think you are right there. That sentence is key.
It's just sometimes difficult to actually realize that one should do what satisfies our needs, and not overdo stuff blindly!

Regarding question 1), do you think it's better to just always broadcast instead of only doing it if a message was received, or time is up, or NPC did something, etc.?

Generally, I first try something like “send a message each time a message is received, but also send a sync-up message every so often in case that message was lost.”

Obviously, if you use TCP, you don't need to worry about this, because no messages will be lost (or, if they are, the entire connection is lost.)

It might be as easy as sending a sync-up once a second. It might be as complex as having the client compute a checksum of state for each entity for certain timestamps, and streaming those checksums to the server, and the server re-sending the data if it detects an out-of-sync.

Also, if the state is small, “broadcast all the state each time the state changes, and also once a second” is nice and robust.

enum Bool { True, False, FileNotFound };

I'll give it some thought but I'm liking that last one approach you mentioned: each time state changes and once a second. Seems good enough!
Thanks once again! 🙂

This topic is closed to new replies.

Advertisement