Merlot Posted December 25, 2022 Share Posted December 25, 2022 Hello everyone! My first post here. I'm trying to build a fixed timestep to align my server with clients on updates. I've been searching for a lot of info online before posting this. In my opinion this should work fine, I have no idea why it's still creating small jitters. The algo on a big scale is something like: PixiTickerLoop { let elapsed = PIXI.Ticker.shared.elapsedMS if (elapsed > 1000) elapsed = this.frameDuration this.lag += elapsed while (this.lag >= this.frameDuration) { //Update the logic this.updateInputs() //Reduce the lag counter by the frame duration this.lag -= this.frameDuration } const lagOffset = this.lag / this.frameDuration this.interpolateSpaceships(lagOffset) } Inside the updateInputs I have something like: this.lerpX.increaseLerp(this._velocity.x) this.lerpY.increaseLerp(this._velocity.y) At this point the velocity is just a constant, to keep things simple. Eg: 10 Now, lerpX and lerpY are a class made the following way: export class Lerp { private from: number = 0 private to: number = 0 private startTime: number = 0 private frame: number = 0 private onFrame: (value: number) => void public logger: boolean = false constructor(from: number, onFrame: (value: number) => void) { this.onFrame = onFrame this.from = from } increaseLerp(to: number, time: number) { this.frame += 1 if (this.startTime != 0) { const duration = time - this.startTime if (this.logger) console.log(`[Lerp] Frame length - ${duration} - ${this.frame}`) } this.startTime = time if (this.frame > 1) this.from = this.to this.to = this.from + to } newFrame(lagOffset: number) { if (!this.needsNewFrame()) return // const value = this.from + (this.to - this.from) * lagOffset const value = Maths.lerp(this.from, this.to, lagOffset) if (this.logger) console.log(`[Lerp] From: ${this.from}, To: ${this.to} = ${value} ( ${lagOffset} )`) this.onFrame(value) } needsNewFrame() { return this.startTime > 0 && Math.abs(this.to - this.from) > 0.001 } reset(current: number) { this.startTime = 0 this.from = current this.to = 0 this.frame = 0 } } Inside the main loop, there is a function that interpolates data. That will call "newFrame" which will then use the callback to update the render position. The logs that a simple run produces are like this: ( considering velocity = 10 ) Quote [UpdateInputs] 1671983837313 SpaceshipSprite.ts:236 [Spaceship] Move called Lerp.ts:22 [Lerp] Frame length - 41.66500000000087 - 2 Lerp.ts:35 [Lerp] From: 11093.168160324418, To: 11103.168160324418 = 11093.99716032442 ( 0.0829000000000201 ) BulletSprite.ts:27 [Bullet][Position][Update] Lerp.ts:35 [Lerp] From: 11093.168160324418, To: 11103.168160324418 = 11097.330360324417 ( 0.4162199999999689 ) Lerp.ts:35 [Lerp] From: 11093.168160324418, To: 11103.168160324418 = 11100.663560324418 ( 0.7495399999999904 ) Lerp.ts:35 [Lerp] From: 11093.168160324418, To: 11103.168160324418 = 11102.330160324418 ( 0.9162000000000375 ) GameManager.ts:229 [UpdateInputs] 1671983837366 SpaceshipSprite.ts:236 [Spaceship] Move called Lerp.ts:22 [Lerp] Frame length - 58.33099999999831 - 3 Lerp.ts:35 [Lerp] From: 11103.168160324418, To: 11113.168160324418 = 11105.663360324419 ( 0.24951999999998634 ) BulletSprite.ts:27 [Bullet][Position][Update] Lerp.ts:35 [Lerp] From: 11103.168160324418, To: 11113.168160324418 = 11107.329960324418 ( 0.41618000000003347 ) Lerp.ts:35 [Lerp] From: 11103.168160324418, To: 11113.168160324418 = 11110.663160324419 ( 0.7494999999999823 ) GameManager.ts:229 [UpdateInputs] 1671983837407 SpaceshipSprite.ts:236 [Spaceship] Move called Lerp.ts:22 [Lerp] Frame length - 41.66500000000087 - 4 Lerp.ts:35 [Lerp] From: 11113.168160324418, To: 11123.168160324418 = 11113.996360324418 ( 0.08282000000000381 ) BulletSprite.ts:27 [Bullet][Position][Update] Lerp.ts:35 [Lerp] From: 11113.168160324418, To: 11123.168160324418 = 11115.662960324418 ( 0.2494799999999782 ) Lerp.ts:35 [Lerp] From: 11113.168160324418, To: 11123.168160324418 = 11120.662760324418 ( 0.7494599999999741 ) Lerp.ts:35 [Lerp] From: 11113.168160324418, To: 11123.168160324418 = 11122.329360324418 ( 0.9161200000000213 ) GameManager.ts:229 [UpdateInputs] 1671983837465 SpaceshipSprite.ts:236 [Spaceship] Move called Lerp.ts:22 [Lerp] Frame length - 49.99799999999959 - 5 Lerp.ts:35 [Lerp] From: 11123.168160324418, To: 11133.168160324418 = 11123.995960324417 ( 0.08277999999999565 ) BulletSprite.ts:27 [Bullet][Position][Update] Lerp.ts:35 [Lerp] From: 11123.168160324418, To: 11133.168160324418 = 11127.329160324418 ( 0.4161000000000172 ) Lerp.ts:35 [Lerp] From: 11123.168160324418, To: 11133.168160324418 = 11130.662360324417 ( 0.749419999999966 ) GameManager.ts:229 [UpdateInputs] 1671983837512 SpaceshipSprite.ts:236 [Spaceship] Move called Lerp.ts:22 [Lerp] Frame length - 49.99799999999959 - 6 Lerp.ts:35 [Lerp] From: 11133.168160324418, To: 11143.168160324418 = 11133.995560324418 ( 0.0827399999999875 ) BulletSprite.ts:27 [Bullet][Position][Update] Lerp.ts:35 [Lerp] From: 11133.168160324418, To: 11143.168160324418 = 11137.328760324417 ( 0.41606000000000903 ) Lerp.ts:35 [Lerp] From: 11133.168160324418, To: 11143.168160324418 = 11140.661960324418 ( 0.7493800000000306 ) Lerp.ts:35 [Lerp] From: 11133.168160324418, To: 11143.168160324418 = 11142.328560324417 ( 0.916040000000005 ) Quote Link to comment Share on other sites More sharing options...
Merlot Posted December 26, 2022 Author Share Posted December 26, 2022 (edited) Just made a quick demo using the code, hopping it will help with debugging. https://playcode.io/1045459 Edited December 26, 2022 by Merlot Quote Link to comment Share on other sites More sharing options...
Merlot Posted December 26, 2022 Author Share Posted December 26, 2022 Looks like if I remove almost all elements in the scene, the jitter is gone. Could it be that the renderer is slowing down everything? Anyone has any experience with this issue? Quote Link to comment Share on other sites More sharing options...
Merlot Posted December 26, 2022 Author Share Posted December 26, 2022 The jitter appears when the frame length becomes unstable. I managed to get this from logs. The normal frame length should be 50. As soon as the length changes, it jitters. Eg below: 50, 67,43,39 then back to 51 again. As long as it stays between 49-51, it's ok. Quote [UpdateInputs] 1672057632736 SpaceshipSprite.ts:244 [Spaceship] Move called Lerp.ts:22 [Lerp] Frame length - 50 - 73 Lerp.ts:35 [Lerp] From: 13777.895379264162, To: 13787.895379264162 = 13779.539579264163 ( 0.16442000000000007 ) Lerp.ts:35 [Lerp] From: 13777.895379264162, To: 13787.895379264162 = 13781.206179264162 ( 0.33108000000001087 ) Lerp.ts:35 [Lerp] From: 13777.895379264162, To: 13787.895379264162 = 13782.872779264162 ( 0.49773999999998525 ) Lerp.ts:35 [Lerp] From: 13777.895379264162, To: 13787.895379264162 = 13784.539379264163 ( 0.664399999999996 ) Lerp.ts:35 [Lerp] From: 13777.895379264162, To: 13787.895379264162 = 13786.205979264161 ( 0.8310600000000068 ) Lerp.ts:35 [Lerp] From: 13777.895379264162, To: 13787.895379264162 = 13787.872579264162 ( 0.9977200000000175 ) GameManager.ts:227 [UpdateInputs] 1672057632803 SpaceshipSprite.ts:244 [Spaceship] Move called Lerp.ts:22 [Lerp] Frame length - 67 - 74 Lerp.ts:35 [Lerp] From: 13787.895379264162, To: 13797.895379264162 = 13792.872379264163 ( 0.49770000000001346 ) Lerp.ts:35 [Lerp] From: 13787.895379264162, To: 13797.895379264162 = 13794.538979264162 ( 0.6643599999999878 ) GameManager.ts:227 [UpdateInputs] 1672057632846 SpaceshipSprite.ts:244 [Spaceship] Move called Lerp.ts:22 [Lerp] Frame length - 43 - 75 Lerp.ts:35 [Lerp] From: 13797.895379264162, To: 13807.895379264162 = 13799.538779264163 ( 0.16433999999998378 ) Lerp.ts:35 [Lerp] From: 13797.895379264162, To: 13807.895379264162 = 13801.205379264162 ( 0.3309999999999945 ) Lerp.ts:35 [Lerp] From: 13797.895379264162, To: 13807.895379264162 = 13802.871979264162 ( 0.4976600000000053 ) Lerp.ts:35 [Lerp] From: 13797.895379264162, To: 13807.895379264162 = 13806.205179264161 ( 0.8309799999999905 ) Lerp.ts:35 [Lerp] From: 13797.895379264162, To: 13807.895379264162 = 13807.871779264162 ( 0.9976400000000012 ) GameManager.ts:227 [UpdateInputs] 1672057632885 SpaceshipSprite.ts:244 [Spaceship] Move called Lerp.ts:22 [Lerp] Frame length - 39 - 76 Lerp.ts:35 [Lerp] From: 13807.895379264162, To: 13817.895379264162 = 13809.538379264162 ( 0.164300000000012 ) Lerp.ts:35 [Lerp] From: 13807.895379264162, To: 13817.895379264162 = 13811.204979264163 ( 0.3309599999999864 ) Lerp.ts:35 [Lerp] From: 13807.895379264162, To: 13817.895379264162 = 13812.871579264163 ( 0.4976199999999972 ) Lerp.ts:35 [Lerp] From: 13807.895379264162, To: 13817.895379264162 = 13814.538179264164 ( 0.664280000000008 ) Lerp.ts:35 [Lerp] From: 13807.895379264162, To: 13817.895379264162 = 13816.204779264162 ( 0.8309400000000187 ) Lerp.ts:35 [Lerp] From: 13807.895379264162, To: 13817.895379264162 = 13817.871379264161 ( 0.997599999999993 ) GameManager.ts:227 [UpdateInputs] 1672057632936 SpaceshipSprite.ts:244 [Spaceship] Move called Lerp.ts:22 [Lerp] Frame length - 51 - 77 Lerp.ts:35 [Lerp] From: 13817.895379264162, To: 13827.895379264162 = 13819.537979264163 ( 0.16426000000000385 ) Lerp.ts:35 [Lerp] From: 13817.895379264162, To: 13827.895379264162 = 13821.204579264162 ( 0.33092000000001465 ) Lerp.ts:35 [Lerp] From: 13817.895379264162, To: 13827.895379264162 = 13822.871179264162 ( 0.49757999999998903 ) Lerp.ts:35 [Lerp] From: 13817.895379264162, To: 13827.895379264162 = 13824.537779264163 ( 0.6642399999999998 ) Lerp.ts:35 [Lerp] From: 13817.895379264162, To: 13827.895379264162 = 13826.204379264163 ( 0.8309000000000105 ) Lerp.ts:35 [Lerp] From: 13817.895379264162, To: 13827.895379264162 = 13827.870979264162 ( 0.9975599999999849 ) Quote Link to comment Share on other sites More sharing options...
Merlot Posted December 26, 2022 Author Share Posted December 26, 2022 Further investigation details:https://docs.google.com/spreadsheets/d/1peuAgTBlZmC8BV40PeucGvvO45ebiY-7OJO_IIlZqqg/edit?usp=sharing Looks like the jitter shows up when my FPS drops from 120 to 60. I have a few frames of position.x increase of 3.3. Check column D. Quote Link to comment Share on other sites More sharing options...
Merlot Posted December 26, 2022 Author Share Posted December 26, 2022 Linking my stackoverflow question as well. https://stackoverflow.com/questions/74922437/pixijs-fixed-step-loop-stutter-jitter Quote Link to comment Share on other sites More sharing options...
Merlot Posted December 26, 2022 Author Share Posted December 26, 2022 Okkkk, mindblowing result. I just found out that this happens even with the most simple version ever. Just by multiplying x = x + speed * delta For the same reason. Sudden drops in FPS. Quote Link to comment Share on other sites More sharing options...
Merlot Posted December 26, 2022 Author Share Posted December 26, 2022 Ok, time to close this thread. Even though I didn't get any help, it helped me track my progress and research. Hopefully it will help some folks in the future. So.. drum rolls please! Time to reveal the solution: const ticker = new PIXI.Ticker(); // The number of frames to use for smoothing const smoothingFrames = 10; // The smoothed frame duration let smoothedFrameDuration = 0; ticker.add((deltaTime) => { // Add the current frame duration to the smoothing array smoothedFrameDuration = (smoothedFrameDuration * (smoothingFrames - 1) + deltaTime) / smoothingFrames; // Update the game logic here // Use the smoothed frame duration instead of the raw deltaTime value }); ticker.start(); Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.