[{"data":1,"prerenderedAt":555},["ShallowReactive",2],{"page-Pak-1":3,"page-count-Pak":47},[4],{"id":5,"title":6,"body":7,"date":532,"description":13,"extension":533,"meta":534,"navigation":104,"path":548,"seo":549,"stem":550,"tags":551,"__hash__":554},"blogs\u002F_legacy\u002F2017\u002F2017-06-24-unrealpak-note.md","UnrealPak的使用笔记",{"type":8,"value":9,"toc":509},"minimark",[10,14,22,27,30,33,172,175,180,183,193,197,200,203,207,210,214,217,220,224,227,230,232,236,239,242,245,249,252,254,257,260,263,266,269,272,275,279,282,285,288,291,294,297,300,303,306,314,317,323,326,332,335,344,350,353,359,362,368,371,374,377,381,389,392,396,402,405,409,412,418,421,424,427,430,433,440,443,446,449,455,458,464,467,473,476,479,485,488,491,494,497,505],[11,12,13],"p",{},"UE4的打包可以通过编辑器直接进行，但是当要实现一些特殊的目标，例如热更新等时，就需要自己使用UnrealPak进行才行。",[11,15,16,17,21],{},"当前使用UE4版本4.16，所有打包",[18,19,20],"strong",{},"仅","在Shiping模式下测试过。",[23,24,26],"h2",{"id":25},"unrealpak","UnrealPak",[11,28,29],{},"UnrealPak在整个打包过程中位于最后面的一个过程，在编辑器中打包的话可以通过输出判断打包的各个阶段。在编译、烘焙之后，如果有勾选Use Pak这个选项的话，引擎就会尝试将以上两个过程中生成的内容打包到Pak中去。",[11,31,32],{},"UnrealPak.exe位于引擎目录下Engine\u002FWin64中，运行程序，在错误提示中有给出基本的使用方法：",[34,35,40],"pre",{"className":36,"code":37,"language":38,"meta":39,"style":39},"language-shell shiki shiki-themes github-light-high-contrast github-dark monokai","UnrealPak \u003CPakFilename> -Test\nUnrealPak \u003CPakFilename> -List\nUnrealPak \u003CPakFilename> -Extract \u003CExtractDir>\nUnrealPak \u003CPakFilename> -Create=\u003CResponseFile> [Options]\nUnrealPak \u003CPakFilename> -Dest=\u003CMountPoint>\nUnrealPak GenerateKeys=\u003CKeyFilename>\nUnrealPak GeneratePrimeTable=\u003CKeyFilename> [-TableMax=\u003CN>]\nUnrealPak \u003CPakFilename1> \u003CPakFilename2> -diff\nUnrealPak -TestEncryption\n\nOptions:\n-blocksize=\u003CBlockSize>\n-bitwindow=\u003CBitWindow>\n-compress\n-encrypt\n-order=\u003COrderingFile>\n-diff (requires 2 filenames first)\n-enginedir (specify engine dir for when using ini encryption configs)\n-projectdir (specify project dir for when using ini encryption configs)\n-encryptionini (specify ini base name to gather encryption settings from)\n-encryptindex (encrypt the pak file index, making it unusable in unrealpak without supplying the key)\n","shell","",[41,42,43,51,57,63,69,75,81,87,93,99,106,112,118,124,130,136,142,148,154,160,166],"code",{"__ignoreMap":39},[44,45,48],"span",{"class":46,"line":47},"line",1,[44,49,50],{},"UnrealPak \u003CPakFilename> -Test\n",[44,52,54],{"class":46,"line":53},2,[44,55,56],{},"UnrealPak \u003CPakFilename> -List\n",[44,58,60],{"class":46,"line":59},3,[44,61,62],{},"UnrealPak \u003CPakFilename> -Extract \u003CExtractDir>\n",[44,64,66],{"class":46,"line":65},4,[44,67,68],{},"UnrealPak \u003CPakFilename> -Create=\u003CResponseFile> [Options]\n",[44,70,72],{"class":46,"line":71},5,[44,73,74],{},"UnrealPak \u003CPakFilename> -Dest=\u003CMountPoint>\n",[44,76,78],{"class":46,"line":77},6,[44,79,80],{},"UnrealPak GenerateKeys=\u003CKeyFilename>\n",[44,82,84],{"class":46,"line":83},7,[44,85,86],{},"UnrealPak GeneratePrimeTable=\u003CKeyFilename> [-TableMax=\u003CN>]\n",[44,88,90],{"class":46,"line":89},8,[44,91,92],{},"UnrealPak \u003CPakFilename1> \u003CPakFilename2> -diff\n",[44,94,96],{"class":46,"line":95},9,[44,97,98],{},"UnrealPak -TestEncryption\n",[44,100,102],{"class":46,"line":101},10,[44,103,105],{"emptyLinePlaceholder":104},true,"\n",[44,107,109],{"class":46,"line":108},11,[44,110,111],{},"Options:\n",[44,113,115],{"class":46,"line":114},12,[44,116,117],{},"-blocksize=\u003CBlockSize>\n",[44,119,121],{"class":46,"line":120},13,[44,122,123],{},"-bitwindow=\u003CBitWindow>\n",[44,125,127],{"class":46,"line":126},14,[44,128,129],{},"-compress\n",[44,131,133],{"class":46,"line":132},15,[44,134,135],{},"-encrypt\n",[44,137,139],{"class":46,"line":138},16,[44,140,141],{},"-order=\u003COrderingFile>\n",[44,143,145],{"class":46,"line":144},17,[44,146,147],{},"-diff (requires 2 filenames first)\n",[44,149,151],{"class":46,"line":150},18,[44,152,153],{},"-enginedir (specify engine dir for when using ini encryption configs)\n",[44,155,157],{"class":46,"line":156},19,[44,158,159],{},"-projectdir (specify project dir for when using ini encryption configs)\n",[44,161,163],{"class":46,"line":162},20,[44,164,165],{},"-encryptionini (specify ini base name to gather encryption settings from)\n",[44,167,169],{"class":46,"line":168},21,[44,170,171],{},"-encryptindex (encrypt the pak file index, making it unusable in unrealpak without supplying the key)\n",[11,173,174],{},"整个程序大致的功能就是可以解压和打包Pak文件：",[176,177,179],"h3",{"id":178},"generatekeys","GenerateKeys",[11,181,182],{},"生成加密Key到文件中，RSA用于对Pak进行签名。",[184,185,186,190],"ul",{},[187,188,189],"li",{},"P：用于RSA的素数p",[187,191,192],{},"Q：用于RSA的素数q",[176,194,196],{"id":195},"generateprimetable","GeneratePrimeTable",[11,198,199],{},"生成素数表，",[11,201,202],{},"TableMax：生成表的停止（最大）数值，默认值10000",[176,204,206],{"id":205},"testencryption","TestEncryption",[11,208,209],{},"测试加密算法的执行，并不检测具体的Key和文件。",[176,211,213],{"id":212},"test","TEST",[11,215,216],{},"对Pak文件进行检测，会对每一个文件进行SHA1校验。",[11,218,219],{},"signed：Pak是否已签名",[176,221,223],{"id":222},"list","List",[11,225,226],{},"列出文件。",[11,228,229],{},"SizeFilter：文件的大小过滤器，会对大于这个大小的文件进行总Size的统计。",[11,231,219],{},[176,233,235],{"id":234},"diff","Diff",[11,237,238],{},"对比两个Pak文件",[11,240,241],{},"nouniques：通过指定nouniquesfile1、nouniquesfile2，是否列出Unique的文件",[11,243,244],{},"signed：Pak是否已签名，不能分开指定。",[176,246,248],{"id":247},"extract","Extract",[11,250,251],{},"解包。",[11,253,219],{},[176,255,256],{"id":256},"构建",[11,258,259],{},"blocksize：块大小，MB或KB单位",[11,261,262],{},"bitwindow：压缩的窗口大小，这个值越大压缩的效果越好，同时消耗的性能也越高。",[11,264,265],{},"patchpaddingalign：是否在进行Patch时启用对齐，不patch时对齐时自动的。",[11,267,268],{},"encryptindex：加密索引，使得文件索引在不提供key的情况下无法解密。",[11,270,271],{},"order：文件读取顺序列表，这个order在cook时会自动生成，一般不用自己提供。uexp会被加上序列值1 \u003C\u003C 29和ubulk会被加上1 \u003C\u003C 30。没有提供order的其他文件将获得 (1 \u003C\u003C 28)。",[11,273,274],{},"sign：对Pak进行签名的RSA的key",[276,277,278],"h4",{"id":278},"create",[11,280,281],{},"文件列表，可在其中单独指定compress和encrypt，但是如果在命令行中指定了的话，就会被强制使用到所有文件。可以是目录或是使用*通配符。",[11,283,284],{},"generatepatch：生成Patch |同时可使用 TempFiles来指定临时目录",[11,286,287],{},"compress：压缩",[11,289,290],{},"encrypt：加密",[276,292,293],{"id":293},"dest",[11,295,296],{},"替换Pak中的MountPoint。",[176,298,299],{"id":299},"加密和压缩",[11,301,302],{},"Pak采用RSA进行签名，AES进行加密，SHA1进行校验。",[11,304,305],{},"加密的流程没有测试，加密的参数可以在ini文件Encryption中进行设置，要使用ini配置的话，需要指定-encryptionini。或者，可以直接在命令行中提供加密参数：",[34,307,312],{"className":308,"code":310,"language":311},[309],"language-text","-Sign=filename\n\n","text",[41,313,310],{"__ignoreMap":39},[11,315,316],{},"或者",[34,318,321],{"className":319,"code":320,"language":311},[309],"-sign=0x123456789abcdef+0x1234567+0x12345abc\n",[41,322,320],{"__ignoreMap":39},[11,324,325],{},"其中第一个数是Exponent，第二个数是Module，第三个数是公钥的Exponent",[34,327,330],{"className":328,"code":329,"language":311},[309],"-aes=blabla\n",[41,331,329],{"__ignoreMap":39},[11,333,334],{},"来提供AES加密秘钥。",[11,336,337,338,343],{},"当前的ProjectLauncher打包，会自动添加-encryptionini，但是只要没有提供Encryption.ini，或者[",[339,340,342],"a",{"href":341},"\u002F2017-06-06-ue4-config-usage\u002F#i","Ini配置","]不正确，就不会进行加密。配置文件的内容应该是类似这样的：",[34,345,348],{"className":346,"code":347,"language":311},[309],"[Core.Encryption]\nSignPak=True\nEncryptPak=True\nrsa.publicexp=blablabla\nrsa.privateexp=blablabla\nrsa.modulus=blablabla\naes.key=blablabla\n",[41,349,347],{"__ignoreMap":39},[11,351,352],{},"由于没有实际测试过，所以不是很明确Encryption的配置能否被打包后的程序自动加载。如果出现了问题，可以检查下CoreDelegate中的：",[34,354,357],{"className":355,"code":356,"language":311},[309],"static FPakEncryptionKeyDelegate& GetPakEncryptionKeyDelegate();\nstatic FPakSigningKeysDelegate& GetPakSigningKeysDelegate();\n",[41,358,356],{"__ignoreMap":39},[11,360,361],{},"引擎在Mount时会从这两个Delegate中获取加密相关的信息，在CoreDelegate的Cpp中有提供",[34,363,366],{"className":364,"code":365,"language":311},[309],"void RegisterEncryptionKey(const char* InEncryptionKey)\n{\n  FCoreDelegates::GetPakEncryptionKeyDelegate().BindLambda([InEncryptionKey]() { return InEncryptionKey; });\n}\n\nvoid RegisterPakSigningKeys(const char* InExponent, const char* InModulus)\n{\n  static FString Exponent(ANSI_TO_TCHAR(InExponent));\n  static FString Modulus(ANSI_TO_TCHAR(InModulus));\n\nFCoreDelegates::GetPakSigningKeysDelegate().BindLambda([](FString& OutExponent, FString& OutModulus)\n{\n  OutExponent = Exponent;\n  OutModulus = Modulus;\n});\n}\n",[41,367,365],{"__ignoreMap":39},[11,369,370],{},"如果没有办法成功注册解密的话，可以尝试模仿引擎代码进行注册来调试一下。",[11,372,373],{},"不过事实上这些功能如果只是打包的话基本不用深究，在使用Project Launcer进行打包时，可以看到编辑器对UnrealPak的调用，将其复制出来，然后进行相应的修改就可以了。",[11,375,376],{},"在进行测试的时候需要注意，UE4对于Asset的加载是有要求的，如果是Shiping烘焙的内容，是无法在编辑器中加载的，必须统一内容的打包格式。",[23,378,380],{"id":379},"mount","Mount",[11,382,383,384,388],{},"Pak在运行时通过Mount将内容读取到游戏中，如果不希望Pak文件被自动加载的话，可以不将其放到[",[339,385,387],{"href":386},"\u002F2017-05-01-ue4-patch-release-dlc\u002F#Maps","自动加载目录","]中。",[11,390,391],{},"手动加载Pak文件时，通常采用的Mount方法有两种。",[176,393,395],{"id":394},"手动mount","手动Mount",[34,397,400],{"className":398,"code":399,"language":311},[309],"EL_LOG(TEXT(\"[AShipIssueGameModeBase] LoadPakMount(): %s\"), *PakPath);\nFString SaveContentDir = PakPath;\nUE_LOG(LogTemp, Log, TEXT(\"[AShipIssueGameModeBase]  ----------- LoadPak: %s --------------\"), *SaveContentDir);\n\n\u002F\u002F获取当前使用的平台,这里使用的是WIN64平台\nIPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();\n\u002F\u002F初始化PakPlatformFile\nFPakPlatformFile* PakPlatformFile = new FPakPlatformFile();\nPakPlatformFile->Initialize(&PlatformFile, TEXT(\"\"));\nFPlatformFileManager::Get().SetPlatformFile(*PakPlatformFile);\n\n\u002F\u002F获取Pak文件\nFPakFile PakFile(&PlatformFile, *SaveContentDir, false);\n\n\u002F\u002F设置pak文件的Mount点.\nFString MountPoint(\"..\u002F..\u002F..\u002F[ProjectName]\u002F\");\nUE_LOG(LogTemp, Log, TEXT(\"[AShipIssueGameModeBase] - Mount Path: %s\"), *MountPoint);\nEL_LOG(TEXT(\"[AShipIssueGameModeBase] Mount Path: %s\"), *MountPoint);\n\nPakFile.SetMountPoint(*MountPoint);\n\u002F\u002F对pak文件mount到前面设定的MountPoint\nif (PakPlatformFile->Mount(*SaveContentDir, 0, *MountPoint))\n{\n  UE_LOG(LogTemp, Log, TEXT(\"[AShipIssueGameModeBase] - Mount Success\"));\n  EL_LOG(TEXT(\"[AShipIssueGameModeBase] Mount Success\"));\n\n}\n",[41,401,399],{"__ignoreMap":39},[11,403,404],{},"这个方法可以手动指定MountPoint，但是通常情况下，除非很确定自己打包了什么，否则很容易丢失各个Asset之间的引用。",[176,406,408],{"id":407},"coredelegate","CoreDelegate",[11,410,411],{},"这个是最近的版本添加的帮助函数，比上面的方法更加的简单实用。",[34,413,416],{"className":414,"code":415,"language":311},[309],"if (FCoreDelegates::OnMountPak.IsBound())\n{\n  if (FCoreDelegates::OnMountPak.Execute(PakPath, 4, nullptr))\n  {\n     EL_LOG(TEXT(\"[AShipIssueGameModeBase] LoadPakDelegate(): OnMountPak.Execute Successful.\"));\n     GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT(\"OnMountPak.Execute Successful.\"));\n  }\n  else\n  {\n    EL_LOG(TEXT(\"[AShipIssueGameModeBase] LoadPakDelegate(): OnMountPak.Execute Falied.\"));\n    GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT(\"OnMountPak.Execute Falied.\"));\n  }\n}\nelse\n{\n  EL_LOG(TEXT(\"[AShipIssueGameModeBase] LoadPakDelegate(): OnMountPak.IsBound() Falied\"));\n  GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT(\"OnMountPak.IsBound() Falied\"));\n}\n",[41,417,415],{"__ignoreMap":39},[11,419,420],{},"使用这个方法会将内容Mount到内容根目录，引擎内部加载Pak文件也是使用的这个方法。",[23,422,423],{"id":423},"路径与引用",[11,425,426],{},"一般情况下使用同一个项目打包的Pak文件，只要打包正确，进行Mount都不会有什么问题。",[11,428,429],{},"而如果使用其他项目进行打包的话，可能会存在一些引用丢失的问题。通常的表现是，使用Mount后的路径可以打开地图，但是地图内物品的材质等关联属性全部都丢失了。",[11,431,432],{},"这个问题通常都是路径问题引起的，另外，在Cook目录中会有AssetRegistry，这个文件是UE用来保存各个Asset之间的引用的，在网上有看到Mount时要自己加载并注册的描述，但是目前版本测试下似乎是会自动加载的。至少在没有主动加载AssetRegistry的情况下，引用已经是正常的了，但是如果出现了引用丢失的问题，可以从这个方面进行一下检查。而且使用CoreDelegate进行Mount的话，是不需要关心这个的。",[11,434,435,436,439],{},"在打包时主要的路径问题来自于打包时的处理机制，UnrealPak会尝试从所有待打包的文件中提取公共的目录作为根目录。而这个根目录之后会被挂在MountPoint之下，那么如果配置有不正确的话，必然会丢失引用。如果引用丢失了的话，对打包的根目录检查也是必要的。在使用",[41,437,438],{},"-create=\u003CResponsFile>","进行打包时，可以在每个文件列的后面指定打包的目标目录，可以一定程度的上解决这个问题。",[176,441,442],{"id":442},"实际使用",[11,444,445],{},"注意：这里记录的是目前项目中使用的路径，并不代表这是一个“好”的方法。因为UnrealPak自主打包无论如何都不会优雅，如果没有紧急的打包需求，建议等官方的Chunk机制等一系列打包功能完善之后直接使用~",[11,447,448],{},"首先，对目标项目ShipIssue进行打包，从Log中拷贝UnrealPak的记录：",[34,450,453],{"className":451,"code":452,"language":311},[309],"D:\\Code\\UE_4.16\\Engine\\Binaries\\Win64\\UnrealPak.exe F:\\Ue_Patch\\1.0_nomap\\WindowsNoEditor\\ShipIssue\\Content\\Paks\\ShipIssue-WindowsNoEditor.pak -create=\"C:\\Users\\Administrator\\AppData\\Roaming\\Unreal Engine\\AutomationTool\\Logs\\D+Code+UE_4.16\\PakList_ShipIssue-WindowsNoEditor.txt\" -encryptionini -enginedir=\"D:\\Code\\UE_4.16\\Engine\" -projectdir=\"E:\\GameDev\\ShipIssue\" -platform=Windows -abslog=\"C:\\Users\\Administrator\\AppData\\Roaming\\Unreal Engine\\AutomationTool\\Logs\\D+Code+UE_4.16\\PakLog_ShipIssue-WindowsNoEditor.log\" -installed -order=E:\\GameDev\\ShipIssue\\Build\\WindowsNoEditor\\FileOpenOrder\\CookerOpenOrder.log -UTF8Output -multiprocess -patchpaddingalign=2048\n",[41,454,452],{"__ignoreMap":39},[11,456,457],{},"然后，将要打包的项目FreePatch进行Cook之后，对拷贝的命令修改：",[34,459,462],{"className":460,"code":461,"language":311},[309],"D:\\Code\\UE_4.16\\Engine\\Binaries\\Win64\\UnrealPak.exe F:\\Ue_Patch\\1.0_nomap\\WindowsNoEditor\\ShipIssue\\Content\\Paks\\Free.pak -create=\"E:\\PakScript\\list.txt\" -encryptionini -enginedir=\"D:\\Code\\UE_4.16\\Engine\" -projectdir=\"E:\\GameDev\\ShipIssue\" -platform=Windows -abslog=\"C:\\Users\\Administrator\\AppData\\Roaming\\Unreal Engine\\AutomationTool\\Logs\\D+Code+UE_4.16\\PakLog_ShipIssue-WindowsNoEditor.log\" -installed -order=E:\\GameDev\\FreePatch\\Build\\WindowsNoEditor\\FileOpenOrder\\CookerOpenOrder.log -UTF8Output -multiprocess -patchpaddingalign=2048\n",[41,463,461],{"__ignoreMap":39},[11,465,466],{},"Order指令的文件可以直接使用Cook出来的，list.txt直接写：",[34,468,471],{"className":469,"code":470,"language":311},[309],"\"E:\\GameDev\\FreePatch\\Saved\\Cooked\\WindowsNoEditor\\FreePatch\\*\" \"..\u002F..\u002F..\u002FShipIssue\u002F*\" –compress\n",[41,472,470],{"__ignoreMap":39},[11,474,475],{},"目标目录写成目标项目的目录，这样的话打包出来的pak文件在自动加载和使用CoreDelegate加载后都能保持正确的引用。",[11,477,478],{},"如果保留原项目名",[34,480,483],{"className":481,"code":482,"language":311},[309],"\"E:\\GameDev\\FreePatch\\Saved\\Cooked\\WindowsNoEditor\\FreePatch\\*\" \"..\u002F..\u002F..\u002FFreePatch\u002F*\" –compress\n",[41,484,482],{"__ignoreMap":39},[11,486,487],{},"需要Mount时自己将MountPoint指定到..\u002F..\u002F..\u002FShipIssue\u002F，自动加载和CoreDelegate加载会加载到..\u002F..\u002F..\u002FFreePatch\u002F导致无法读取到地图中物体引用的材质。",[11,489,490],{},"因此并不推荐这样做~",[11,492,493],{},"通常情况下，只要mount之后的路径在\u002FShipIssue\u002F下的结构与原本在Content\u002F下的结构相同，材质之类的引用就不会丢失。丢失的情况，一般从路径方面检查下先比较好。",[11,495,496],{},"更新：由于Pak的加载确实有些迷，经常会有朋友发邮件或者留言来问我。但是从打包到加载的过程中的可变量太多，我也无法准确的知道每个人遇到的问题。所以在这里将测试打包用到的代码分离成一个插件。",[11,498,499,500,504],{},"其实插件本身并不复杂，只是在使用UFS的API遍历访问而已。主要的作用是可以方便对加载过程的理解和问题的排查。详情请参考[",[339,501,503],{"href":502},"\u002Fpage\u002Fue4-pak-file-view\u002F","UE4文件查看插件","]。",[506,507,508],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html.sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}",{"title":39,"searchDepth":53,"depth":59,"links":510},[511,525,529],{"id":25,"depth":53,"text":26,"children":512},[513,514,515,516,517,518,519,520,524],{"id":178,"depth":59,"text":179},{"id":195,"depth":59,"text":196},{"id":205,"depth":59,"text":206},{"id":212,"depth":59,"text":213},{"id":222,"depth":59,"text":223},{"id":234,"depth":59,"text":235},{"id":247,"depth":59,"text":248},{"id":256,"depth":59,"text":256,"children":521},[522,523],{"id":278,"depth":65,"text":278},{"id":293,"depth":65,"text":293},{"id":299,"depth":59,"text":299},{"id":379,"depth":53,"text":380,"children":526},[527,528],{"id":394,"depth":59,"text":395},{"id":407,"depth":59,"text":408},{"id":423,"depth":53,"text":423,"children":530},[531],{"id":442,"depth":59,"text":442},"2017-06-24","md",{"layout":535,"status":536,"published":104,"author":537,"author_login":539,"author_email":540,"wordpress_id":541,"wordpress_url":542,"date_gmt":543,"excerpt":544},"post","publish",{"display_name":538,"login":539,"email":540,"url":39},"风铃","flinkor","flinkor@foxmail.com",1790,"\u002F\u002F?p=1790","2017-06-24 11:37:17 +0000",{"type":8,"value":545},[546],[11,547,13],{},"\u002F2017-06-24-unrealpak-note",{"title":6,"description":13},"_legacy\u002F2017\u002F2017-06-24-unrealpak-note",[552,26,553],"UE4","Pak","Jr-XOewnXJ3-UJQa19DQu02xnktkiNhN_su7wcAU86Y",1788763180057]