16.66ms帧次。当sleep()只经过整毫秒时,如何获得完美的60 fps? 我喜欢用C++和java做小游戏,但有些东西一直困扰着我,我还从来没有完全理解如何去补救它。 睡眠C++和java只在毫秒内工作。意思是如果你这么做了 startTime=clock(); -------Execute everything in that frame----- endTime=clock(); sleep(x-(endTime-startTime));

16.66ms帧次。当sleep()只经过整毫秒时,如何获得完美的60 fps? 我喜欢用C++和java做小游戏,但有些东西一直困扰着我,我还从来没有完全理解如何去补救它。 睡眠C++和java只在毫秒内工作。意思是如果你这么做了 startTime=clock(); -------Execute everything in that frame----- endTime=clock(); sleep(x-(endTime-startTime));,java,c++,sleep,frame-rate,Java,C++,Sleep,Frame Rate,如果x为16,则每秒获得62.5帧 如果x为17,则每秒可获得58.8帧 这两者都不是完美的60适合显示器的刷新率 但我注意到一些像Warframe这样的游戏会说“16.66毫秒帧时间”,这意味着他们的引擎能够以更高的精度睡眠 那么你是如何得到完美的60分的呢 最好是C++,因为这是我现在正在使用的,但是对于java也有帮助。 < p>我不知道这是否是创建渲染循环的正确方法,但是有更多的方法可以比睡眠>代码>睡眠。查看nanosleep我不知道这是否是构建渲染循环的正确方法,但有比睡眠更多的睡眠

如果x为16,则每秒获得62.5帧 如果x为17,则每秒可获得58.8帧

这两者都不是完美的60适合显示器的刷新率

但我注意到一些像Warframe这样的游戏会说“16.66毫秒帧时间”,这意味着他们的引擎能够以更高的精度睡眠

那么你是如何得到完美的60分的呢


最好是C++,因为这是我现在正在使用的,但是对于java也有帮助。

< p>我不知道这是否是创建渲染循环的正确方法,但是有更多的方法可以比<代码>睡眠>代码>睡眠。查看
nanosleep

我不知道这是否是构建渲染循环的正确方法,但有比
睡眠
更多的睡眠方法。查看
nanosleep

你对计时工作的理解过于简单。在用户空间软件中不进行精确计时。精确计时在别处进行

软件构成下一帧。完成后,它将帧传递给驱动程序,驱动程序以正确的时间和速率显示帧。通常,驱动程序可以触发软件渲染下一帧


软件就是不能在长时间睡眠的情况下工作。当它需要等待某件事情时,它实际上是在等待它需要等待的事情。

你对计时工作的理解过于简单。在用户空间软件中不进行精确计时。精确计时在别处进行

软件构成下一帧。完成后,它将帧传递给驱动程序,驱动程序以正确的时间和速率显示帧。通常,驱动程序可以触发软件渲染下一帧


软件就是不能在长时间睡眠的情况下工作。当它需要等待某件事情时,它实际上是在等待它需要等待的事情。

单靠
睡眠
是错误的:您需要以固定的速率进行调度,并且由您指定纳秒精度。使用

final ExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(task, 
    TimeUnit.SECONDS.toNanos(1/60), 
    TimeUnit.SECONDS.toNanos(1/60), 
    TimeUnit.NANOSECONDS);

单独依靠
睡眠
无论如何都是错误的:您需要以固定速率进行调度,并且由您以纳秒精度指定。使用

final ExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(task, 
    TimeUnit.SECONDS.toNanos(1/60), 
    TimeUnit.SECONDS.toNanos(1/60), 
    TimeUnit.NANOSECONDS);

最好的方法是完全避免睡眠,并使用一些API在屏幕刷新后立即调用代码。这在很大程度上取决于您使用的图形库,但您正在寻找类似于JavaScript中著名的requestAnimationFrame()函数的东西


如果您没有访问此类API的权限,那么正如其他回答所述,在Java中,您可以使用
System.nanoTime()
Thread.sleep(long millis,int nanos)

最好的方法是完全避免睡眠,并在屏幕刷新后立即使用调用代码的API。这在很大程度上取决于您使用的图形库,但您正在寻找类似于JavaScript中著名的requestAnimationFrame()函数的东西


如果您没有访问此类API的权限,那么与其他回答状态一样,在Java中,您可以使用
System.nanoTime()
Thread.sleep(long millis,int nanos)

您无法保证进程将睡眠多长时间。事实上,您的程序可以在睡眠之间暂停任意长度的时间,并且每秒会暂停数千次。有一些工具可以根据计时的错误程度来测量系统中的抖动

相反,您应该在nanoTime中估计下一个进程应该在什么时候醒来并为差异而休眠,这样可以避免累积错误

long intervalNanos = ....
long nextNanos = System.nanoTime() + intervalNanos;
while(running) {
    doSomething();
    long now = System.nanoTime();
    if (now > nextNanos) {
       // we are not keeping up.
       nextNanos = now + intervalNanos;
       continue;
    }
    long delay = (nextNanos - now) / 1000000;
    Thread.sleep(delay);
    nextNanos += intervalNanos;
}

你无法保证这个过程会休眠多久。事实上,您的程序可以在睡眠之间暂停任意长度的时间,并且每秒会暂停数千次。有一些工具可以根据计时的错误程度来测量系统中的抖动

相反,您应该在nanoTime中估计下一个进程应该在什么时候醒来并为差异而休眠,这样可以避免累积错误

long intervalNanos = ....
long nextNanos = System.nanoTime() + intervalNanos;
while(running) {
    doSomething();
    long now = System.nanoTime();
    if (now > nextNanos) {
       // we are not keeping up.
       nextNanos = now + intervalNanos;
       continue;
    }
    long delay = (nextNanos - now) / 1000000;
    Thread.sleep(delay);
    nextNanos += intervalNanos;
}

您不应该有一个计时器,该计时器在特定时间休眠,并在不同的线程中运行更新和渲染方法

相反,在上一次迭代中测量渲染所需的时间。 将时间(或基于时间计算的乘法器)输入更新方法

e、 g

现在,您不必急于操纵场景图并在特定的计时器间隔内渲染新视图

在显示fps值的游戏中,它们使用如下内容:

private boolean runGame;
private double tpf;

public void stop() {
    runGame = false;
}

public void run() {
    rungame = true;

    // repeat until the game should stop
    while(runGame) {
        // calculate the time per frame of the last frame
        tpf = (System.nanoTime() / 1000 / 1000) - tpf;
        // calculate the frames per second to show it in a debug window or else
        double fps = (tpf > 0 ? (1.0 / tpf) : 0);

        // handle all actions on the scenegraph
        update(scenegraph, tpf);
        // render the new view for each camera (e.g. each players view)
        renderViews(cameras, scenegraph);
    }
}

如果将fps显示到debugconsole,您将无法读取它,因为它更改得太快:)保存最后一分钟的fps并显示平均值。

您不应该有一个计时器,它会在特定时间休眠,并在不同的线程中运行更新和渲染方法

相反,在上一次迭代中测量渲染所需的时间。 将时间(或基于时间计算的乘法器)输入更新方法

e、 g

现在,您不必急于操纵场景图并在特定的计时器间隔内渲染新视图

在显示fps值的游戏中,它们使用如下内容:

private boolean runGame;
private double tpf;

public void stop() {
    runGame = false;
}

public void run() {
    rungame = true;

    // repeat until the game should stop
    while(runGame) {
        // calculate the time per frame of the last frame
        tpf = (System.nanoTime() / 1000 / 1000) - tpf;
        // calculate the frames per second to show it in a debug window or else
        double fps = (tpf > 0 ? (1.0 / tpf) : 0);

        // handle all actions on the scenegraph
        update(scenegraph, tpf);
        // render the new view for each camera (e.g. each players view)
        renderViews(cameras, scenegraph);
    }
}

如果将fps显示到debugconsole,您将无法读取它,因为它变化太快:)保存最后一分钟的fps并显示平均值。

对于Windows,大多数具有以固定频率运行的线程的游戏物理引擎使用类似于此代码的代码。延迟基于高频时钟的原始读取,以防止长时间内的任何漂移。Th