Overwatch Gameplay Architecture and Netcode
Created on 2020-08-18T00:45:07.253963
- "singleton contacts"/"deferment": post a message that some decal should be created and let a decal system deal with it in a later pass. centralizes code so multiple sites post the request but only one site does the complex work of projecting the decals. can budget message handling so the jobs are done across frames to avoid performance spikes.
- Time is quantized to 16ms (public) and 7ms (tournamnet) frames. this clock is then synchronized across clients. roll-over accumulator (time is added to bucket, then subtracted when bucket is run, which keeps fractional time.)
- Inputs go in to a ring buffer; if server response confirms client was correct then prediction continues. if response is inconsistent with client, then simulation diverged and you have to resolve the fork.
- Server has buffer of unprocessed inputs; when buffer is starved it asks clients to simulate faster to build up a backlog then tells them to stop. clients include all inputs since the last unacknowledged frame for each packet they send.
- Custom scripting language is used for scripting abilities; its build to handle rolling the simulation back in time to apply corrections and then move forward again.
- Hurt and heal changes are also posted (singleton contact) and resolved later on.
- Server favors an attacker for hit prediction unless the victim has activated some mitigating ability (invuln frames are trusted over hit frames)
- Entities hold many components. systems hold code and no state. components hold state and no code. shared code lives in utilities. complex side effects should be deferred to later. systems can't call in to one another.
- Systems worked on tuples of components but were later changed to an ad-hoc system where they requested sibling components. developer suggests it would have been better to stick with the tuple strategy since it makes it explicit what systems are capable of accessing.
- Tuple strategy also allows indicating whether access is read or read/write. systems which write separate components but read shared components can be run in parallel. this was done with a fork/join model.
- "pit of success": confine a process to a series of "rules of engagement" but make sure those rules are designed to ensure things come out well.
- Component iterators: an array which is sorted by memory address; sorting by address increases cache locality.
- Destroying entities is deferred to end of frame. creating entities happens when desired, but the entity's components are added to extra "just created" arrays which are walked over, then insertion sorted in to the happier primary array.