2017-10-12 73 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