UE4中Pak文件的读取规则
本文鏈接 https://blog.csdn.net/BDalasja/article/details/95618330
最近項(xiàng)目轉(zhuǎn)戰(zhàn)UE4了,需要研究UE4的熱更,就此研究了一下PAK文件的相關(guān)內(nèi)容。
pak文件是UE打包后的一種文件格式,所有的資源文件都是存儲(chǔ)在這個(gè)文件中。我們?cè)诖虬蟮捻?xiàng)目下,可以發(fā)現(xiàn) content目錄下有一個(gè)Paks目錄,目錄中一般會(huì)有一個(gè)pak文件和一個(gè)sig文件。既然叫Paks,說明肯定會(huì)有多個(gè)pak文件。以堡壘之夜為例,可以看到Paks目錄下有40+的pak文件。那么這些pak文件是怎么組織的?引擎是怎么知道哪個(gè)文件在哪個(gè)pak文件中的?多個(gè)pak文件中如果同時(shí)有某個(gè)資源(熱更的情況),又是如何處理覆蓋關(guān)系?
1. Paks中的pak文件在游戲啟動(dòng)的時(shí)候,會(huì)全部自動(dòng)"掛載"
什么叫掛載?
代碼里面叫做Mount 。Mount 是一個(gè)有別與Load的概念,Mount是讀取pak文件中的文件信息,就是獲取pak文件中有哪些文件,以便后續(xù)查找文件的時(shí)候,確定pak中是否有指定的文件。
什么時(shí)候掛載?
app啟動(dòng)的時(shí)候,在LaunchEngineLoop中的PreInit函數(shù)中,會(huì)調(diào)用FPakPlatformFile::MountAllPakFiles("Game/Content/Paks/") 。這個(gè)函數(shù)就是Paks下面所有的pak文件并遍歷掛載。
2. 多個(gè)Pak如何決定加載及搜索順序?
引擎內(nèi)部維護(hù)一個(gè)已經(jīng)掛載的pak文件列表,當(dāng)需要打開其中的文件的時(shí)候,會(huì)遍歷這些pak中的文件列表,查看該pak是否包含該文件,如果包含,則認(rèn)為該文件包含在改pak中。
這個(gè)文件搜索方法表面:
3. pak文件名可以控制讀取順序
那么這個(gè)pak文件列表中的順序是如何來決定的呢?閱讀代碼我們會(huì)發(fā)現(xiàn),它使用一個(gè)ReadOrder的字段來排序,Order越大,就排在前面,Order一樣,則默認(rèn)按文件名排序。這個(gè)ReadOrder有以下規(guī)則:
Paks文件夾中,并已游戲名開頭的文件起始Order為4;Content目錄Order為 3 。如果paks文件夾中pak的文件名不是以游戲名為開頭,則會(huì)滿足Content這個(gè)條件。
Engine目錄下的pak文件Order為2,游戲的用戶存儲(chǔ)目錄則為1,其他為0 。
文件夾自身的優(yōu)先級(jí)邏輯如下:
在前兩條規(guī)則的基礎(chǔ)上,文件名以_P.pak 為結(jié)尾的,享有額外Order。額外Order最低100。如果結(jié)尾形如_n_P.pak 其中n是數(shù)字,則會(huì)再額外得到 n乘以100的Order值。 例如 _2_P.pak 則額外Order為 300 。
// 如果文件名以 "_P.pak" 結(jié)束 if (PakFilename.EndsWith(TEXT("_P.pak"))) {uint32 ChunkVersionNumber = 1;FString StrippedPakFilename = PakFilename.LeftChop(6);// 倒著檢測(cè),看_P.pak 前面有沒有 _n 結(jié)構(gòu)int32 VersionEndIndex = PakFilename.Find("_", ESearchCase::CaseSensitive, ESearchDir::FromEnd);if (VersionEndIndex != INDEX_NONE && VersionEndIndex > 0){int32 VersionStartIndex = PakFilename.Find("_", ESearchCase::CaseSensitive, ESearchDir::FromEnd, VersionEndIndex - 1);if (VersionStartIndex != INDEX_NONE){VersionStartIndex++;FString VersionString = PakFilename.Mid(VersionStartIndex, VersionEndIndex - VersionStartIndex);if (VersionString.IsNumeric()){// 如果有數(shù)字并大于1 則認(rèn)為這個(gè)數(shù)字是一個(gè)Version;為了保證基礎(chǔ)100的Order,這里會(huì)額外 +1int32 ChunkVersionSigned = FCString::Atoi(*VersionString);if (ChunkVersionSigned >= 1){ChunkVersionNumber = (uint32)ChunkVersionSigned + 1;}}}}// 計(jì)算OrderPakOrder += 100 * ChunkVersionNumber; }結(jié)論
通過上面的內(nèi)容我們可以得出結(jié)論:
這幾個(gè)結(jié)論,可以推到出一個(gè)新的話題,那就是熱更。通過下載新的pak,并控制搜索順序,則可以很容易“屏蔽”老pak中的資源文件。當(dāng)然這個(gè)新的pak需要一定規(guī)則生成,是一個(gè)補(bǔ)丁包,不是完整pak包。好在UE本身就提供差異修改打patch的工具, 下一篇我們就來討論一下UE4的patch熱更方案。 UE4 版本Patch方案
總結(jié)
以上是生活随笔為你收集整理的UE4中Pak文件的读取规则的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Peer-To-Peer 综述(P2P技
- 下一篇: 澳大利亚:令人钦羡的高福利国家 - 老牛