WP7 - XNA載入圖片策略與效能

  • 6788
  • 0
  • WP
  • 2011-11-02

WP7 - XNA載入圖片策略與效能

遊戲的圖片載入是最重要的功能,遊戲要玩的順暢,如何讓載入的速度變快也是一門學問,

在學習做2D遊戲的時候,上網搜尋遊戲素材,會發現很多素材都是如下圖

PeopleW

會將很多動作或是一堆物件做在同一張圖片上,而不是個別單一圖檔,

這不是為了網路下載素材方便才這樣做的,

而是因為遊戲載入受到硬體限制,所以希望載入的次數越少越好,

才會將相關的動作或是物品全都集合成一張圖,然後只要載入一次大圖就可以了。

 

雖然聽起來很合理,不過身為專業的阿宅工程師,不可以道聽塗說、人云亦云,

因此我們就來做做實驗吧!以下都是HD7實機測試。

首先產生100張200X200的png圖,

Small

再用此100張圖拼成一張200X200的大圖,載入程式碼如下:

   1: protected override void LoadContent() {
   2:     // Create a new SpriteBatch, which can be used to draw textures.
   3:     spriteBatch = new SpriteBatch(GraphicsDevice);
   4:  
   5:     Start();
   6:     LoadLarge();
   7:     End("LoadLarge cost");
   8:  
   9:     Start();
  10:     LoadSmallList();
  11:     End("LoadSmallList cost");
  12:  
  13: }
  14:  
  15: private void LoadLarge() {
  16:     Large = Content.Load<Texture2D>("Large");
  17: }
  18:  
  19: private void LoadSmallList() {
  20:     for (int i = 0; i < 100; i++) {
  21:         SmallList[i] = Content.Load<Texture2D>(string.Format("Small ({0})", i + 1));
  22:     }
  23: }

LoadLarge就是載入一張大圖,LoadSmallList就是載入100張小圖

執行六次得到的數據如下:

  一 二 三 四 五 六 平均
Large 193 182 195 227 249 228 212
SmallList 446 439 461 441 462 440 451

 

接著我們將兩個載入方式互換,先載入100張小圖,再載入一張大圖,得到如下數據

  一 二 三 四 五 六 平均
Large 182 181 170 184 183 181 180
SmallList 533 473 452 472 472 473 494

 

單位都是毫秒。

由此可知第一次載入會多花費一些時間,但是一張大圖的效率也比多張小圖好上2.1到2.7倍。

不過這是在所有小圖都可以放入大圖內的情形,但是效能差距還是挺明顯的。

 

知道載入次數對效能影響,再來試試看載入怎樣的大圖會最快,

由於手機載入圖片有最大2048X2048的限制,

所以我們測試的圖片大小分別為1000X1000、2000X500 以及 500X2000,

這三張圖的面積都一樣,理論上是可以塞一樣多的東西,數據如下:

  一 二 三 單個檔案大小
1000x1000 44 44 41 192K
2000x500 44 44 43 111K
500x2000 43 43 40 305K

測了三次就不想測了,結果是都一樣。

由上一個測試可以發現第一次載入都會有特別的時間消耗,

因此這次的測試在載入這三個圖之前有先載入一個小圖,

之後這三個圖的載入時間才會如此接近。

 

由上面第一個實驗可以知道載入速度看的是載入的次數,

而第二個實驗三個檔案大小不一樣,載入速度卻是一樣的,難道是看檔案面積?

其實載入的確除了看次數,另外一個就是看檔案大小,只是檔案大小不是看PNG的檔案,而是看XNA編譯後的XNB檔,

 

看了一下圖檔的大小,原本只有192K的圖檔,編譯成XNB檔後竟然有3.81MB,這是發生甚麼事??

XNA為了載入快速,會捨棄需要編碼的圖檔格式(如Jpg,Png等),全都轉成不用解碼可以直接讀取的檔案,

因此1000x1000的檔案大小就變成1000*1000*4(bytes) 大約等於3.81MB,而載入的速度就取決於XNB的大小。

 

甚麼?你說身為專業的阿宅工程師,不可以沒做實驗就認為XNB真的比較快??

那就來簡單做個實驗,關鍵程式碼如下:

 

   1: protected override void LoadContent() {
   2:     // Create a new SpriteBatch, which can be used to draw textures.
   3:     spriteBatch = new SpriteBatch(GraphicsDevice);
   4:  
   5:  
   6:     Start();
   7:     Small = Content.Load<Texture2D>("Small");
   8:     End("Small cost");
   9:  
  10:     Start();
  11:     Large = Content.Load<Texture2D>("Large");
  12:     End("L cost");
  13:  
  14:     Start();
  15:     Large2 = Texture2D.FromStream(GraphicsDevice, TitleContainer.OpenStream("Large2.png"));
  16:     End("L2 cost");
  17: }
  18:  

我們要從專案裡直接讀取檔案的話,要把檔案放到主專案(不是Content專案),

並且Build Action設定成None或是Content,

Copy to Output Directory設定為Copy always。

之後在程式裡可以用TitleContainer取得Stream,再藉由Texture2D.FromStream讀取進來,

數據如下:

  一 二 三 四 五 六 平均
xnb 166 162 153 162 163 163 161.5
png 964 920 895 920 919 920 923

由此可以看出xnb的確載入速度更快。

 

結論:

如果遊戲的物件沒有特殊需求,全都放在一張圖檔裡載入的速度是最快的。

而一張圖載入的速度和xnb檔案大小成正比。

xnb檔案大小直接從size決定。

 

這樣在用XNA做遊戲時對於資源的運用就會有個底了!