XNA中, ResourcePool枚舉類型由MDX中的4個改為了2個, 分別是Automatic和Manual, 枚舉名稱也改為了ResourceManagmentMode。其中Automatic對應mdx中的Managed,Manual對應Default。
以Manual方式建立的資源被儲存在video memory或AGP memory中。而Automatic類型的資源則儲存在系統記憶體中,在需要使用的時候自動複製到顯存裡,預設情況下,xna中的資源都儲存為Automatic方式。兩者的區別在於由於Manual類資源分派在顯存中,因此,每當重設裝置之後,顯存中的這些資料都會丟失,因此需要手動重新載入;由於重設並不會改變device的屬性,所以儲存在系統記憶體中的資源仍然是可用的,xna會自動管理這些資源。這裡,會引起重設裝置的操作通常包括改變視窗大小,已最小化的視窗,在視窗和全螢幕模式直接切換。以Manual方式建立的資源通常有更好的效能,xna會把這些資源放到最利於device訪問的位置,但如果需要頻繁重設裝置,那麼就必須反覆載入這些資源。當然,對於xbox來說,重設裝置的情況發生的比較少。按照xna team的建議,應該儘可能使用Automatic方式來建立資源。
在編寫程式時,應該把建立Automatic和Manual資源的代碼分開:
LoadAutomaticResource();
LoadManualResource();
在DeviceCreate事件觸發時,應該同時調用這2個方法:
private void graphics_DeviceCreated(object sender, EventArgs e)
{
LoadAutomaticResource();
LoadManualResource();
}
graphicsDevice.reset += new System.EventHandler(OnDeviceReset)
而在Reset事件觸發時,只需調用LoadManualResource()方法。
在XNA遊戲架構中,不需要直接連接事件處理代碼,Game類的LoadGraphicsContent方法簡化了這個過程。
在建立和重設裝置時,會自動調用LoadGraphicsContent方法,並且根據loadAllContent標誌來選擇建立哪些代碼,所以我們只要把載入資源的代碼放到適當位置:
protected override void LoadGraphicsContent(bool loadAllContent)
{
if (loadAllContent)
{
// TODO: Load any ResourceManagementMode.Automatic content LoadAutomaticResource();
}
// TODO: Load any ResourceManagementMode.Manual content LoadManualResource();
}
此外,對於用Content PipeLine載入的資源來說,不需要對這些資源編寫dispose方法。Content PipeLine會為我們管理這些資源,在需要釋放這些資源時只需要調用UnLoad()方法就可以了。
content.Load<model>(“terrain”); //load the terrain model and texture if the model have a texture
content.Load<model>(“house”);
// do something with terrain and house
content.UnLoad();
Content PipeLine在編譯期間會對所載入的資源進行預先處理,所有資源檔(比如.jpg,.fbx,.x,.tga)都被重新打包為.xnb作為尾碼名的二進位檔案。對於載入模型來說,不需要顯示載入所需紋理,Content PipeLine會自動載入所需紋理,但需要保證這些紋理和模型檔案在同一目錄下,或其他Content PipeLine能找到的地方。載入模型時,如果不同模型使用了同一個紋理,那麼這張紋理只會被載入一次。假設我們為使用Content PipeLine建立的資源編寫了dispose方法,那麼對於使用了同一張紋理的不同模型來說,dispose其中一個模型,將帶來一些問題。
注意,一個程式中可以建立多個Content PipeLine對象,比如我們可以為每個關卡建立一個,這樣我們就能在建立新關卡時載入所有資源,而在離開時保證清理了所有資源。
總的來說,xna大大簡化了載入和管理資源的難度,讓我們可以把更多注意力放到遊戲性上^^