日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

UE4中Pak文件的读取规则

發(fā)布時(shí)間:2023/12/14 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 UE4中Pak文件的读取规则 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本文鏈接 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è)文件搜索方法表面:

  • apk文件列表決定了查找順序。
  • 如果多個(gè)pak都包含某個(gè)文件,則肯定使用順序在前的pak
  • 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í)邏輯如下:

    int32 FPakPlatformFile::GetPakOrderFromPakFilePath(const FString& PakFilePath) { if (PakFilePath.StartsWith(FString::Printf(TEXT("%sPaks/%s-"), *FPaths::ProjectContentDir(), FApp::GetProjectName()))) {return 4; } else if (PakFilePath.StartsWith(FPaths::ProjectContentDir())) {return 3; } else if (PakFilePath.StartsWith(FPaths::EngineContentDir())) {return 2; } else if (PakFilePath.StartsWith(FPaths::ProjectSavedDir())) {return 1; }return 0; }
  • 在前兩條規(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é)論:

  • Paks文件夾中的pak文件會(huì)全部自動(dòng)掛載
  • 非Paks文件夾中的pak文件需要自行手動(dòng)掛載,效果和Paks文件夾中一致
  • 使用一定格式的文件名,可以控制pak中文件的搜索順序
  • 這幾個(gè)結(jié)論,可以推到出一個(gè)新的話題,那就是熱更。通過下載新的pak,并控制搜索順序,則可以很容易“屏蔽”老pak中的資源文件。當(dāng)然這個(gè)新的pak需要一定規(guī)則生成,是一個(gè)補(bǔ)丁包,不是完整pak包。好在UE本身就提供差異修改打patch的工具, 下一篇我們就來討論一下UE4的patch熱更方案。 UE4 版本Patch方案

    總結(jié)

    以上是生活随笔為你收集整理的UE4中Pak文件的读取规则的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。