I’m having a hard time getting multiplayer to work for my game.
I think this is due to the fact that I cannot really wrap my head around the client/server code execution dynamics (think isLocalPlayer and such). I get the relationship between clients and server, but I cannot logically put that in to code-wise considerations.
What I’m looking for ultimately, is a tried-and-true simple way of instantiating and destroying networked physics objects. I can get two players to move, but when trying to spawn projectiles the players shoot, I run in to problems.
Some scenarios:
A: A player shoots a projectile, given some input - spawning a projectile for all clients.
B: The server spawns some object, say given a timer - spawning this object, properly networked.
C: A networked object needs to be destroyed - self explanatory.
I hope my conundrum makes sense. Any help would be much appreciated
The thing is, there isn’t a one size fits all solution for this problem. The solution varies depending on the needs of the game.
For example, I’m building a game set in the age of sail. When a player wants to fire a cannonball from their ship, here is the simplified version of the process that happens using the Unet HLAPI:
Player presses spacebar to fire
A script on that client’s Player GameObject issues a “fire cannon” command to the server
The server does various checks that it is ok to fire, and determines what cannon port, then instantiates and spawns the cannonball, as well as applying a force to the cannonball.
The cannonball is spawned on all clients with the force applied
On the server, if the cannonball exists for more than a specified amount of time, goes below a certain Y axis value (hits the water), or impacts another ship, the server calls NetworkServer.Destroy on the cannonball object, and applies any effects of the impact.
This works great for my game primarily due to the pace of the game’s action. I use server authority for all objects, even the ship the player is sailing, so when the cannonball is instantiated it appears at the correct location right outside the gun being fired (both the movement of the ship and the spawning of the cannonball are affected by the same amount of server lag, so the cannonball placement always looks correct on all clients). When a player goes to adjust the speed or turn their ship, they expect a rather sluggish response from an old sailing ship, so waiting on the server to send updates to the position of everything works just fine for me.
Doing it as above would be a terrible implementation for any kind of run and gun shooter game though. The movement of the player’s character would be far too delayed to wait for the server to process a movement and then send the update back to the player’s client, so you’d either want to use local authority for the player’s character or a hybrid where the player responds fast locally but this is just a prediction of what the server will do. The problem then is when you fire a bullet you also can’t just have the server instantiate/spawn it, because the bullet will be spawned at the spot where the player’s gun used to be a fraction of a second ago instead of where the gun was locally when the player pressed the fire button. So then you need a new solution for how to instantiate/spawn bullets that takes this into account.
This was really insightful, thank you. This leads me to think:
Can I see a code example of your cannon firing procedure?
In my FPS case, would something like instantiating and applying force on the client, and then do a NetworkServer.Spawn(bullet) do the trick/part of the trick?
It is a little long since I left out a lot of details specific to my game, but I can post it.
That can work. You may want to sync up the two one that client is told to spawn the bullet from the server, or you might want to just use the one you instantiated on the client. Depends on the speed of the bullet and other factors. There are other threads on the topic that better explain it than I can.