mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-25 11:18:55 +00:00
Updated documentation.
This commit is contained in:
parent
cccbeb1c29
commit
114e6b0501
@ -1,11 +1,11 @@
|
||||
Under the current "input delay" algorithm, the lag of a single player would cause all the other players to receive outdated commands, e.g. when at a certain moment
|
||||
- player#1: renderFrameId = 100, significantly lagged due to local CPU being overheated
|
||||
- player#1: renderFrameId = 100, significantly lagged due to local CPU overheated
|
||||
- player#2: renderFrameId = 240
|
||||
- player#3: renderFrameId = 239
|
||||
- player#4: renderFrameId = 242
|
||||
|
||||
players #2, #3 #4 would receive "outdated(in their subjective feelings)" from then on, and be forced to rollback many frames.
|
||||
players #2, #3 #4 would receive "outdated(in their subjective feelings) but all-confirmed commands" from then on, thus forced to rollback and chase many frames - the lag due to "large range of frame-chasing" would then further deteriorate the situation - like an avalanche.
|
||||
|
||||
In a "no-server & p2p" setup, I couldn't think of a proper way to cope with such edge case. On the frontend we could only mitigate the impact to players #2, #3, #4 by certain buffering mechanisms.
|
||||
In a "no-server & p2p" setup, I couldn't think of a proper way to cope with such edge case. Solely on the frontend we could only mitigate the impact to players #2, #3, #4, e.g. a potential lag due to "large range of frame-chasing" is proactively avoided in `<proj-root>/frontend/assets/scripts/Map.js, function update(dt)` for more information.
|
||||
|
||||
However in a "server as authority" setup, the server could force confirming an inputFrame without player#1's upsync, and notify player#1 to apply a "roomDownsyncFrame" as well as drop all its outdated local inputFrames.
|
||||
|
@ -440,7 +440,7 @@
|
||||
"array": [
|
||||
0,
|
||||
0,
|
||||
216.05530045313827,
|
||||
209.73151519075364,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
|
@ -631,7 +631,7 @@ cc.Class({
|
||||
--------------------------------------------------------
|
||||
*/
|
||||
if (renderFrameId1 < self.chaserRenderFrameId) {
|
||||
// The actual rollback-and-replay would later be executed in update(dt).
|
||||
// The actual rollback-and-chase would later be executed in update(dt).
|
||||
console.warn("Mismatched input detected, resetting chaserRenderFrameId: inputFrameId1:", inputFrameId1, ", renderFrameId1:", renderFrameId1, ", chaserRenderFrameId before reset: ", self.chaserRenderFrameId);
|
||||
self.chaserRenderFrameId = renderFrameId1;
|
||||
} else {
|
||||
@ -798,15 +798,16 @@ cc.Class({
|
||||
}
|
||||
|
||||
let t1 = performance.now();
|
||||
// Use "fractional-frame-chasing" to guarantee that "self.update(dt)" is not jammed by a "large range of frame-chasing". See `<proj-root>/ConcerningEdgeCases.md` for the motivation.
|
||||
const prevChaserRenderFrameId = self.chaserRenderFrameId;
|
||||
let nextChaserRenderFrameId = (prevChaserRenderFrameId + self.maxChasingRenderFramesPerUpdate);
|
||||
if (nextChaserRenderFrameId > self.renderFrameId) nextChaserRenderFrameId = self.renderFrameId;
|
||||
self.rollbackAndReplay(prevChaserRenderFrameId, nextChaserRenderFrameId, self.chaserCollisionSys, self.chaserCollisionSysMap);
|
||||
self.rollbackAndChase(prevChaserRenderFrameId, nextChaserRenderFrameId, self.chaserCollisionSys, self.chaserCollisionSysMap);
|
||||
self.chaserRenderFrameId = nextChaserRenderFrameId; // Move the cursor "self.chaserRenderFrameId", keep in mind that "self.chaserRenderFrameId" is not monotonic!
|
||||
let t2 = performance.now();
|
||||
|
||||
// Inside "self.rollbackAndReplay", the "self.latestCollisionSys" is ALWAYS ROLLED BACK to "self.recentRenderCache.get(self.renderFrameId)" before being applied dynamics from corresponding inputFrameDownsync, REGARDLESS OF whether or not "self.chaserRenderFrameId == self.renderFrameId" now.
|
||||
const rdf = self.rollbackAndReplay(self.renderFrameId, self.renderFrameId+1, self.latestCollisionSys, self.latestCollisionSysMap);
|
||||
// Inside "self.rollbackAndChase", the "self.latestCollisionSys" is ALWAYS ROLLED BACK to "self.recentRenderCache.get(self.renderFrameId)" before being applied dynamics from corresponding inputFrameDownsync, REGARDLESS OF whether or not "self.chaserRenderFrameId == self.renderFrameId" now.
|
||||
const rdf = self.rollbackAndChase(self.renderFrameId, self.renderFrameId+1, self.latestCollisionSys, self.latestCollisionSysMap);
|
||||
|
||||
self.applyRoomDownsyncFrameDynamics(rdf);
|
||||
let t3 = performance.now();
|
||||
@ -1011,7 +1012,7 @@ cc.Class({
|
||||
return inputFrameDownsync;
|
||||
},
|
||||
|
||||
rollbackAndReplay(renderFrameIdSt, renderFrameIdEd, collisionSys, collisionSysMap) {
|
||||
rollbackAndChase(renderFrameIdSt, renderFrameIdEd, collisionSys, collisionSysMap) {
|
||||
if (renderFrameSt >= renderFrameIdEd) {
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user