Drive client networking from a real-time tick#74
Conversation
Player position/scale broadcast and remote-player interpolation previously ran on the HeroController.Update hook with Time.deltaTime, so they stalled whenever the game was paused (pause menu, inventory, map). Paused players became invisible to peers who didn't already know their position, and remote players froze on screen. Move the tick to a dedicated DontDestroyOnLoad MonoBehaviour using Time.unscaledDeltaTime, and add a 500 ms position heartbeat so stationary players remain discoverable to late joiners.
Pause-State ImprovementsThis is a really good solution to the pause-state problem. Moving away from A few ideas that could make the implementation even cleaner and more efficient: 1. Use Unity
|
Stopwatch is wall-clock and keeps running while the app is suspended or backgrounded, producing a delayed burst update on resume. Time.unscaledDeltaTime advances only with Unity frames, so the heartbeat throttle pauses cleanly with the app and stays consistent with the unscaled time already used for interpolation in this method.
|
Appreciate the suggestions. Here's some thoughts: (1) PlayerLoop has a major downside in that if another mod sets it, it breaks the code we've set. (2a) I like the idea, but I believe we would run into the issue again if timescale is changed in a state we didn't hook into; notably by other mods. (2b) Consider this: if a local player enters a pause state, and a remote player enters the scene 8.0s later, that local player will be invisible on the remote player's screen for potentially up to 9.5s. That's the worst case scenario, but even after 2.5s paused, players could totally miss each other during the subsequent 2500ms gap. Keep in mind that this is a highly disruptive issue for player vs. player games, so I don't really want to compromise for small bandwidth wins. (3) Good point. Made another commit to address this. |
|
On (1) PlayerLoop: Fully agree, that was a bad suggestion for a modded environment. On (2a) Time.unscaledDeltaTime risk from other mods: I believe this concern doesn't actually apply here. Souce Citation: https://docs.unity3d.com/ScriptReference/Time-unscaledDeltaTime.html On (2b) Back-off heartbeat visibility gap: You're completely right the math confirms it, tbh i am never thinking these things regarding pvp so good catch. |
|
Ah, right -- you're correct about 2a, that's my mistake. I can look into state-based syncing sometime soon. |
|
In general these changes are welcome, but we should also consider getting rid of pausing for local players altogether. This is also done in HKMP and is much preferred, because being in a multiplayer lobby and being able to pause your own game doesn't make a whole lot of sense. Most of the code in Perhaps it is best if we simply move that call ( |
Agreed. I'll look into that when I have time. |
Player position and interpolation previously ran on the HeroController.Update hook with Time.deltaTime, so they stalled whenever the game was paused (pause menu, inventory, map). Paused players became invisible when other player clients didn't already know their position, and remote players froze on screen. This led to silly situations where a player opening their map or their inventory could render them invisible to players just entering the scene. Moved the tick to a dedicated DontDestroyOnLoad MonoBehaviour using Time.unscaledDeltaTime, and add a 500 ms position heartbeat so stationary players remain discoverable to late joiners. Given the duration of scene transitions, this should be adequate.