2017-10-12 76 views
0

长篇故事: 我想在LibGDX中创建一个加载屏幕,不仅需要加载资源(如纹理和音频),还需要创建世界对象(超过10个百万个对象) - 我可能想研究未来对象数量的减少,但我的问题仍然适用,无论它是一个对象还是数万亿。LibGDX在重载处理期间加载屏幕

在对象初始化过程中,GDX render()方法因为我假设的滞后而停止。它会滞后很多整个应用程序进入“没有响应”几秒钟。

我一直在研究几个月没有太多的发现。我发现的主题或我问的人中的90%总是说同样的话;使用AssetManager。我试过这个,但它似乎只支持资产,而不是重处理世界对象。有人告诉我可以支持自定义类,但是由于缺少文档,我从来没有这样做。

与我的最相似的最佳主题是这个one,它给了我一个在Gdx.app.postRunnable()中使用Gdx.app.postRunnable()的想法。结果是这样的:

Gdx.app.postRunnable(new Runnable() { 
    @Override 
    public void run() { 

     // do some heavy processing 
     // set loading screen percent to x% 

     Gdx.app.postRunnable(new Runnable() { 
      @Override 
      public void run() { 

       // do some more heavy processing 
       // set loading screen percent to y% 

      } 
     }); 

    } 
}); 

该解决方案效果很好。它做了大量的处理,设置加载屏幕的百分比然后绘制它。所以为了展示清酒,这个解决方案解决了我从未画过百分比的问题。但是,这种解决方案仍然会将应用程序变成重要过程之间的“不响应”;这会冻结最终的音乐播放。

通过在postRunnables内部添加足够的postRunnables,不会有滞后现象,因为繁重的流程不再存在 - 而是建立在分解为小流程的重流程之上,解决了“无响应”状态。尽管这样的许多postRunnables对于“干净的代码”并不是很实用,因为它需要超过30个postRunnables,上面的代码只有2个。代码很容易变得丑陋,因此我寻求替代方案。

This帖子相当有趣,解释了我正面临的完全相同的问题,但结果并没有解决。

我在Java Swing中通过创建两个线程来实现此目的;一个主线程和一个加载屏幕线程(LCThread)。当进入加载屏幕时,LC线程开始绘制加载屏幕,而主线程进行繁重的处理。完成后,主线程使用之前处理的对象。可悲的是我不能将它转换成LibGDX,因为两个线程不能单独绘制。

短篇小说:我需要的代码,同时借鉴的情况下(在render()方法处理)播放音乐时显示加载屏幕,都没有落后装载重型后台处理(初始化大量的对象)加载屏幕它输入的应用程序“没有响应”。

你有什么建议吗?

回答

1

你可以分解你的GameObject,使它释放处理器。希望这会加载块,并保持渲染循环免费播放音乐。基本上所有的加载和创建资产都通过AssetManager,并在渲染循环中检查以查看游戏处于何种状态并据此采取行动。 自定义GameObject加载器。 GameObject只是一个泛型类将其应用于您的项目specifecs。

在AssetManger更新(int millis)方法中,它将CPU产生到指定的毫秒数。如果分解所有处理并将其置于其自己的AssetLoader中,那么AssetManager会更新该时间并且不会阻止该CPU。

public class GameObjectLoader extends SynchronousAssetLoader<GameObject, GameObjectLoader.GameObjectParameters> { 

    public GameObjectLoader(FileHandleResolver resolver) { 

     super(resolver); 
    } 

    @Override 
    public GameObject load(AssetManager assetManager, String fileName, FileHandle file, GameObjectParameters parameter) { 

     TextureAtlas atlas = assetManager.get(parameter.src, TextureAtlas.class); 
     ShaderProgram shaderProgram = assetManager.get(parameter.shaderSrc, ShaderProgram.class); 
     JsonValue json = assetManager.get(parameter.jsonSrc, JsonValue.class); 
     Calculation calculation = assetManager.get(parameter.id, Calculation.class); 

     GameObject gameObject = new GameObject(
      atlas.findRegion(parameter.name), 
      shaderProgram, 
      json, 
      calculation 
     ); 

     assetManager.unload(parameter.id); // unload it otherwise it stays in memory 

     return gameObject; 
    } 

    @Override 
    public Array<AssetDescriptor> getDependencies(String fileName, FileHandle file, GameObjectParameters parameter) { 

     Array<AssetDescriptor> dependencies = new Array<AssetDescriptor>(); 

     dependencies.add(new AssetDescriptor<TextureAtlas>(parameter.src, TextureAtlas.class)); 
     dependencies.add(new AssetDescriptor<ShaderProgram>(parameter.shaderSrc, ShaderProgram.class, parameter.shaderParameter)); 
     dependencies.add(new AssetDescriptor<JsonValue>(parameter.jsonSrc, JsonValue.class)); 
     dependencies.add(new AssetDescriptor<Calculation>(parameter.id, Calculation.class)); 

     return dependencies; 
    } 


    public static class GameObjectParameters extends AssetLoaderParameters<GameObject> { 

     // maybe you have a lot of game logic and dont need to load everything from disk make a custom loader for that too 
     public String id = ""; 
     public String src = ""; 
     public String name = ""; 
     public String jsonSrc = ""; 
     public String shaderSrc = ""; 
     public ShaderProgramLoader.ShaderProgramParameter shaderParameter = null; 
    } 
} 

AssetLoaders不需要有文件来处理它仍然可以与一个工作。

class CalculationLoader extends SynchronousAssetLoader<Calculation, AssetLoaderParameters<Calculation>> { 

    public CalculationLoader(FileHandleResolver resolver) { 

     super(resolver); 
    } 

    @Override 
    public Calculation load(AssetManager assetManager, String fileName, FileHandle file, AssetLoaderParameters<Calculation> parameter) { 

     // this is the heavy processing 
     // the AssetManager dictates how many of these per cycle will be calculated 
     return new Calculation(); 
    } 

    @Override 
    public Array<AssetDescriptor> getDependencies(String fileName, FileHandle file, AssetLoaderParameters<Calculation> parameter) { 

     return null; 
    } 

    public static class CalculationParameters extends AssetLoaderParameters<Calculation> { 


    } 
} 
+0

谢谢你的回答。但加载“资产”(纹理,音频,着色器)不是主要的恶棍,正如我所说的那样,我正在进行非常繁重的处理,例如大量的对象初始化和数学计算。我不太明白如何将它合并到一个'AssetManager'中。 – Squiddie

+0

我编辑了答案,AssetManager规定每个周期将加载/计算多少资产,以便它不会阻止CPU。 – Tejay

+0

这看起来很有希望。但结果是一样的,但我可能误解了你。 “分解所有处理”是什么意思?你的意思是有多个AssetLoaders?在我的测试中,我只有一个 – Squiddie