Let’s consider a game where you can fire (travelling) projectiles that can hit NPCs or walls.
What is the better option regarding Netcode for GO:
-
When a player fires, a ServerRPC is called to instantiate a NetworkObject projectile, which in turn instantiates it on all the clients and syncs its position over time. It’s purely visual on clients, since collision is handled on the server.
When the projectile hits something on the server, it will trigger hit logic (server-side) and spawn a NetworkObject VFX on all clients. This makes 2 NetworkObjects that have to be synced (bullet and impact vfx).
-
When a player fires, a serverRpc is called from the client. The server then:
- instantiates a server-only projectile to handle logic
- calls a ClientRpc on all clients to instantiate a client-only projectile on each client
- calculates the projectile movement over time
- when it hits something, it will trigger a ClientRpc on all clients to instantiate a client-only VFX
So no synced NetworkObject but RPC calls instead.
Intuitively, I’d think that option 2 would be faster and lighter on the network, at the cost of being a bit less convenient to write. Is that correct or am I missing something?
You still need a way to identify on all clients what that projectile is.
The server may tell clients that “projectile 2583” has impacted. So each client needs to have a projectile registry where they can look up projectile 2583 and destroy it. This registry must not run out of sync.
Since you said that the projectile is client-only I assume it will not have a NetworkObject, thus no global object id hash and it cannot be looked up in NetworkManager’s SpawnManager.
Ultimately that solution is lighter on traffic but makes your projectiles client-authoritative in some way. If there is any mistake on the client side as to what trajectory the projectile is taking the impact may occur at a different place than client would expect.
Also depends on whether the projectiles runs linearly (eg fast bullet) or whether it has homing attributes, or is a cluster munition that explodes into multiple smaller fragments which each cause damage individually.
I would go for #1 because it serves all use cases. If there is need for optimization, it is relatively straightforward to change some or all projectiles to behave like in #2.
No, the VFX object is not networked. Server just tells clients that projectile X has impacted, and where. Projectile X then Instantiates the same vfx object at impact position for all clients, as defined by the projectile type.
That’s a very valid point regarding bullets.
So regarding the impact VFX, the server would call ClientRPCs so clients instantiate them?
Yes. The server sends the “impact” RPC and then clients would do the necessary impact stuff like spawning VFX, playing audio, and such. Only the logical effects need to be applied by the server, such as hitpoint deduction.
1 Like
You’d go for option 1 basically. As CodeSmile suggests there are drawbacks to it.
I’d be curious to know the cost on traffic of doing this VS instantiating a NetworkObject. I wouldn’t be surprised if a NetworkObject spawn would just be ClientRpc with a prefab Id. I might test that.