Common Practice for Client-Triggered Events?

Hi, I am wondering if I should run functions that define some sort of client-triggered behavior only on the server and then as a multicast, or if I should immediately run it on the client that caused this event as well.

So, to my knowledge there are basically 2 ways to deal with client-input: have the client call a server function and then, if other clients need to know about any changes, either set replicated variables or call a multicast-function.

My question is: should I wait for the multicast function (or replicated variable) to arrive on the “original” client? Or should I call the multicast function (or set the variable…) on that client right away to avoid an unnecessary delay? If so, wouldn’t that cause problems when the update from the server arrives at the client, basically triggering the same response again?

As an example:

I have a function…

  • “StartAttackAnimation” that interacts with the animation blueprint and starts the actual animation.
  • “InitiateAttack” that is called by the client and calls
  • “InitiateAttack_Server” which calls the multicast function
  • “InitiateAttack_Multi” which calls “StartAttackAnimation” on every client and the server.

Is it better to have the client call “StartAttackAnimation” (or alternatively “InitiateAttack_Multi”) inside “InitiateAttack” when the message to the server is getting sent or wait until the multicast-call gets back?

Well I’m not sure if this is common practice or not, but the way I’m currently doing it (and the way I’ve seen others do it) is pretty much like you said, except with one addition:

  1. Make sure the actor you’re calling these from has it’s owner set (pawn or controller)
  2. When InitiateAttack_Multi happens, just get the owner’s pawn/controller and check “Is Locally Controlled” - if it’s false then do StartAttackAnimation. If it’s true do nothing (since you already called StartAttackAnimation directly from that client).

So in my case I was doing tracer fire, which I want no lag on:

  1. Client weapon calls DoTracerFX (not replicated), then ServerDoTracerFX (Server Only)
  2. ServerDoTraceFX then calls AllMachinesDoTracerFX (Multicast)
  3. AllMachinesDoTracerFX then checks if this weapons owner is locally controlled - if not, then DoTracerFX

Well, since I posted this question over a year ago, it’s not so much on my mind anymore. But thanks for the reassurance anyway. I went from a direct control kind of game to a top-down RTS kind of setting, where lag-compensation is hardly needed. I’m still thinking about making it a hybrid though, where you can directly control a unit in first or third person. At the moment, I hope I can get away without lag-compensation anyway, because if you want to do it thoroughly, it’s a fricking box of pandora… If you have other projectiles than instant “traces”, you need unrelated actors for them on client/server, then you would need a complicated “roll-back” system for hit detection etc etc. And since it will primarily be a single player game with a cooperative multiplayer, people will just need a good connection… After experiencing “Dungeon of the Endless”, I know that a game can be far from technologically perfect and still be fun and succesful ^^