0

I ran into a problem, where doing everything on a single thread may lead to some lags. The problem is, when I start to create loads of new objects (like 300 per second), my physics rate drops.

I sort all rendering objects each frame, so I would know which one to draw in which order, this might be the reason why it can handle only so little, but even if that was removed, there still would be like max operations per update, otherwise physics will lag.

Any ideas on how to achieve the correct zOrder, or remove possible physics lags?

Or detach physics from rendering ... ?

My game loop:

while (isRunning) {

    currentFrameTime = System.nanoTime();
    passedTime = currentFrameTime - lastFrameTime;
    lastFrameTime = currentFrameTime;

    physicsPassedTime += passedTime;
    updatePassedTime += passedTime;

    if (physicsPassedTime >= (double) 1_000_000_000 / physicsRate) {

        physicsPassedTime = 0;

        PhysicsUpdate();
    }

    if (updatePassedTime >= (double) 1_000_000_000 / refreshRate) {

        updatePassedTime = 0;

        Update();
        Render();
        LateUpdate();
    }
}
Mahrkeenerh
  • 1,104
  • 1
  • 9
  • 25
  • 3
    Most game engines detach physics from rendering, and only execute physics on specified update intervals. They may also sort objects based on their velocity, and update the slower moving objects less often. – Richard Barker Apr 04 '21 at 21:11
  • 1) method names should NOT start with an upper case character. Follow the conventions used in the JDK. 2) Don't use a while loop to control the renderer. Most of the time will be spent looping doing nothing. Instead, use a Swing Timer to schedule the animation. – camickr Apr 04 '21 at 21:14
  • @RichardBarker I didn't think of just adding a separate loop for physics, but that could totally work out. I'll try having two loops – Mahrkeenerh Apr 04 '21 at 21:38
  • @SMAEL Well, it's not quite as simple as just making a second loop. The loops both need to be running at the same time, so you need 2 separate threads. Or better yet, 2 separate timers, that way the time between calls is consistent. – Charlie Armstrong Apr 04 '21 at 22:05
  • @CharlieArmstrong only the physics update needs consistent times between calls, so the regular update can just go and do whatever it wants in it's own time, and slow the fps to whatever it will – Mahrkeenerh Apr 04 '21 at 22:17
  • 1
    @SMAEL Sure. The critical piece I was trying to get at is that you can't just stick the second loop in after the first one, because the first loop is an infinite loop, so you'll never get to the second loop. You need two separate threads to run in parallel. One or both of those threads could/should be a timer, but it's critical that they are two separate threads. – Charlie Armstrong Apr 04 '21 at 22:27
  • 1
    @CharlieArmstrong right, sorry if I didn't make it clear either. Yes I know, the physics will be on second thread. And since you are already a second one suggesting the timer, I'll take a look at that too – Mahrkeenerh Apr 04 '21 at 22:38
  • In most game engines, the physics thread is on the CPU while the rendering thread is on the GPU. That's where you should be going with your render loop. – Richard Barker Apr 05 '21 at 00:10
  • 1
    @RichardBarker I am not sure how, but I think I utilize the GPU for rendering in some way, because when I unlocked the FPS, (I got over 600k in a simple demo), my GPU went straight to like 80% of usage. I won't pretend I know how it works (I don't), but it seems to work, and it's a school project, so I'm pretty happy with how it's going. – Mahrkeenerh Apr 05 '21 at 00:17
  • @CharlieArmstrong if I understand this correctly, the timer should work: while(running), update, measure how much time that took, if there is some time left until next update - wait that time? – Mahrkeenerh Apr 05 '21 at 13:05
  • @SMAEL That sounds like it's much more complicated than it needs to be. You should be able to just set the timer to call a TimerTask's method repeatedly, and then the timer takes care of all this for you, and it even launches a new thread all on its own. See [`Timer#schedule()`](https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/util/Timer.html#schedule(java.util.TimerTask,long,long)) and [`Timer#scheduleAtFixedRate()`](https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/util/Timer.html#scheduleAtFixedRate(java.util.TimerTask,long,long)) – Charlie Armstrong Apr 05 '21 at 15:57

1 Answers1

1

Looks like the best solution (as suggested in comments) will be to run a second loop on a second thread with just physics update, and everything else on the other thread.

That way frame drops should not intervene with the physic updates.

Edit: Implemented this, and works like charm. I'll mark the answer when I'll be able to.

Mahrkeenerh
  • 1,104
  • 1
  • 9
  • 25