How can I efficiently make a delta snapshot that accounts for entities/components that have been added/removed?
In reference to the snapshot and delta compression approach popularized by Quake 3, but with ECS.
Understand the delta should only contain changes — makes sense.
However, if a snapshot delta no longer contains some component x, how does the client know if it’s because there is no state change or because the server removed the component? Same for entities, an entity may just not have any state change over the last few ticks, or, it may have been destroyed on the server, perhaps it was killed but we missed that state update.
Now, I could:
- Encode this into the actual diff as proposed in the comments, e.g. component x from previous snapshot no longer exists in latest snapshot. This of course would not be compatible with how my deltas are currently being auto generated by XORing two snapshots.
- Include ALL — in view — entity IDs and component types in a given snapshot delta packet even if the corresponding components are zero'd out (no change). Packet size concerns here as we’re no longer sending ‘only changes’ — e.g. if entity ID is 1 byte, component tag is 1 byte; 100 entities each with 5 networked components is already 600 bytes uncompressed even if the component data is unchanged and zeroed out (such as XOR).
- Use a separate command system to relay key entity or component events e.g. entity x destroyed/spawned, etc., but that seems like overkill since it could be handled implicitly via state updates.
Example: P2 -- standing in view of P1 -- goes AFK for a few seconds and so the last x snapshots for P1 didn't contain the P2 entity. P1 doesn't know if P2 is dead and so it’s entity needs destroying, or it's actually just doing nothing. The reverse is also true, i.e. P2 could have been killed and the server destroyed that entity, but P1 missed the state update that indicated the death.
A somewhat related note but please feel free to stop reading: Quake 3 as far as I can see here will include all entities in the snapshot including an indicator if the entity is null (destroyed I assume). In the ECS world where we don’t have one struct representing an entity, but instead have many (components), if the same approach were to be followed for an entity’s components it could lead to a bulky delta — as per my original concern. Whilst not related to my question, diff is also much easier with the single struct approach since it would have many fields and you could simply XOR with a previous version and RLE out the zeros — also doesn’t work for components which would defeat the RLE.