Android Gameloop (openGL ES 2.0) 的问题

Posted

技术标签:

【中文标题】Android Gameloop (openGL ES 2.0) 的问题【英文标题】:Problems with Android Gameloop (openGL ES 2.0) 【发布时间】:2014-05-20 17:03:04 【问题描述】:

概述

在我的游戏循环中出现很多不连贯的动画问题。我正在运行循环 onDrawFrame 如您所见,如果循环时间过长,我的循环允许跳帧(我使用的是固定时间增量,60fps 的时间“切片”为 16.666666 毫秒)。

我已经确认跳帧时会发生卡顿。

出现跳帧时,如何防止动画出现断断续续的情况?

如果它绝对必须跳帧(我承认在某些设备上有时会发生这种情况),我该如何减轻这种断断续续的情况?

自上次调用以来,onDrawFrame(GL10 gl) 似乎在 24 毫秒内被调用。

在我的 Google Nexus 10 平板电脑上,我的实际渲染可能需要 5 到 14 毫秒,而我的游戏更新只需要 0 到 4 毫秒,所以大部分时间它应该很适合 16.6666 时间片。但是,当我从 onDrawFrame 中删除所有内容时,它的调用间隔似乎在 16 到 25 毫秒之间。 (大多数时候,它超过 16 毫秒),因此,它跳过了很多帧——即使没有调用渲染或更新!!

这似乎违背了以 60FPS 运行的设备的全部意义 - 这个 VSync 是这样做的吗?超过 16 毫秒有什么意义?

我尝试过的事情

好的,我尝试生成一个单独的线程来运行我的更新(同样,将它们限制为每秒 60 次)。我仍然遇到问题。

我也尝试过插值,但这又没有任何区别。 (我将发布一个单独的问题,看看我是否正确)。

我真的很挣扎,所以我希望有人能提供帮助!

代码

float interpolation;
long nextGameTick = System.currentTimeMillis();
//loop counter
int loops;
//This is the amount of frames that we allow our app to skip before logic updating is affected (generally shouldn't happen)
final int maxFrameskip = 5;                             
//Game updates per second
final int ticksPerSecond = 60;
//Amount of time each update should take        
final int skipTicks = (1000 / ticksPerSecond);

    public void onDrawFrame(GL10 gl) 


        //Set/Re-set loop back to 0 to start counting again
        loops=0;

        while(System.currentTimeMillis() > nextGameTick && loops < maxFrameskip)

        SceneManager.getInstance().getCurrentScene().updateLogic();
        nextGameTick+=skipTicks;
        timeCorrection += (1000d/ticksPerSecond) % 1;
        nextGameTick+=timeCorrection;
        timeCorrection %=1;
        loops++;
        tics++;

     

        interpolation = (float)(System.currentTimeMillis() + skipTicks - nextGameTick)
              / (float)skipTicks; 

    render(interpolation);

应用插值

render(float interpolation)

    //This example shows interpolation for X axis only.  Y position (spriteScreenY is assumed to be valid)
    interpolatedPosX = spriteGridX+(SpriteXVelocity*dt)*interpolation;
    spriteScreenPosX = interpolationPosX * screenWidth;

    drawSprite(spriteScreenX, spriteScreenY);           



【问题讨论】:

你在你的游戏循环中分配了内存吗(请记住,使用 for-each 语法遍历集合会分配一个迭代器)? GC 可能会导致卡顿。检查“D/dalvikvm GC_CONCURRENT freed”的 logcat 调试消息,它会显示它暂停了多长时间。 嗨@thanks for the comment - 在我的循环中没有发生分配 - 这是我检查的第一件事,所以我很早就排除了 - 干杯! @Zippy 你解决了这个问题吗。我也有同样的问题 嗨@Sunny,不幸的是,我还没有解决它。我已经尝试了所有方法,但在跳过帧时仍然有断断续续的动画。现在,我只是忍受它,但需要在某个时候重新访问它。如果您遇到任何建议,很想听听他们的意见!! :-( 【参考方案1】:

尝试使用 RENDERMODE_WHEN_DIRTY。这意味着不再使用 onDrawFrame,而是在游戏循环中使用 requestRender()。

【讨论】:

以上是关于Android Gameloop (openGL ES 2.0) 的问题的主要内容,如果未能解决你的问题,请参考以下文章

如何暂停和恢复 GameLoop?

gameloop和deltatime插值c ++

C# 控制台应用程序 - gameloop / 多个对象

在 Windows 窗体中实现 gameloop [关闭]

iPhone Gameloop 从一个单独的线程渲染更新

FPS Lag 调度程序?