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