Specifically, what should the per-entity IInputComponentData include?
Suppose I only place the destination coordinates into the IInputComponentData , which is set within a GhostInputSystemGroup system in response to a player’s mouse click. Consequently, each entity has destination data in the command stream, and this data can be used as input for downstream predicted systems. However, this data requires processing to be useful, and the resulting output is not an IInputComponentData . For example, a pathfinding system would take the destination as input and generate a path, but the path itself is a dynamic buffer, not IInputComponentData .
Right, you could put the direction or target coordinate of each unit. Normally this would be controller input like forward, lef, shoot and this is the equivalent, as in this is what the unit is doing atm until the user changes it. This makes the most sense where the server is just running the navigation, then the client is just sending his coordinate or direction and it’s processed as normal, it’s just coming over the network. The result of the navigation is then replicated to all clients (including the owner).
But with client side prediction added it gets trickier. We don’t really support this or have any solution made for this. You’d need to be able reset the navigation system in the prediction loop and then re-navigate the path it gives you up to latest tick. Maybe it’s enough to only reset at the first prediction tick.
Q1: I understand that NetCode for Entities is not typically designed for RTS games, though I hope this is primarily due to scaling concerns. To use an extreme example: if there were only one unit in the entire game session, would client prediction work for the pathfinder? (To clarify, in NetCode samples, the IInputComponentData is used directly to control character movement direction without further processing; in this case, however, it does need to be further processed).
It actually scales easily to RTS number of units, you can try out thousands of asteroids in the NetcodeSamples project. However, normally RTS games do not synchronize thousands of units, they depend on determinism and just needing the clients and server to process the same inputs, then they simulate exactly the same output for those inputs, then you don’t need to synchronize actual unit position/etc. No need for any rollback as it’s always identical outputs.
Client prediction needs something close to determinism to work (to minimize mis-predictions) but doesn’t require 100% accurate determinism. How it works with a pathfinder depends on the implementation.
Q2: Suppose the pathfinder is a predicted system that runs on both the server and the client. Should the generated path be a dynamic buffer?
If so, should it be a ghost field? But snapshot update, assuming it happens in this frame, is still not instataneous, which defeats the whole purpose of client prediction?
If not, then even though client and server can compute individually, how does roll back work?
What is the recommended approach to make this work?
I’d think you would synchronize the result of the simulation, so where the ghosts end up after the navigation is done and has moved it already. Rollback will be the tricky part, like I mentioned above, depends on what kinds of implementation you have. To actually rollback you’d need to be able to reset the navigation or pathfinding to the current state of the ghosts (the prediction system will roll the transforms/ghostfields back automatically), then redo the navigation according to the input/direction for each predicted tick.
I know this isn’t very clear and unfortunately we don’t have a recommendation for this at the moment. The easiest is to not do client prediction and only run the navigation/simulation on the server. Only use interpolation, then it can scale to a lot of units and will look perfect as they play back on the clients. The usual way of hiding the latency is to have some delay where some animation plays or something happens to let you know the command was registered before the actual movement arrives from the server.
Well, in that case, which Netcode solution is suitable for an RTS in which 70-100 synchronized objects are present at the same time? (there may be about 5-15 for each of the clients)
That scale is probably ok with the methods discussed so far, with just interpolation it would be fine, with some movement logic which is rollback compatible those number of predicted units (5-15) is probbaly ok too. With RTS I was thinking thousands of units, and the traditional way of doing that is with lockstep determinism. That’s not just the netcode but more like the engine needs to support that, at least every feature which affects the simulation. There is also a delay there (like with interpolation), while inputs are gathered, but then the simulation is 100% deterministic everywhere. You could do that with Photons Quantum solution afaik, but maybe others can suggest other solutions like that.