[{"data":1,"prerenderedAt":1956},["ShallowReactive",2],{"page-UE4-8":3,"page-count-UE4":1955},[4,224,995,1159,1832],{"id":5,"title":6,"body":7,"date":199,"description":13,"extension":200,"meta":201,"navigation":204,"path":216,"seo":217,"stem":218,"tags":219,"__hash__":223},"blogs\u002F_legacy\u002F2017\u002F2017-10-14-ue4-config-setting.md","UE4的配置界面写入",{"type":8,"value":9,"toc":192},"minimark",[10,14,17,26,31,34,37,40,43,54,57,61,64,70,73,76,79,107,110,117,122,125,128,132,135,138,161,164,167,170,173,179,182],[11,12,13],"p",{},"UE4的Config系统使用起来很方便，但是如果要让制作出来的插件\u002F项目更方便的让其他人设置，就需要将其写到编辑器的配置列表中。",[11,15,16],{},"当前使用的UE4版本为4.18.0 P4。",[11,18,19,20,25],{},"这里的内容是以",[21,22,24],"a",{"href":23},"\u002F2017-06-06-ue4-config-usage\u002F","Conifg系统","的使用为前提的，只是简略的记录了插件制作过程中，将Conifg注入到编辑器界面的过程。",[27,28,30],"h2",{"id":29},"udevelopersettings","UDeveloperSettings",[11,32,33],{},"让配置类继承自UDeveloperSettings是最简单的配置实现方式。",[11,35,36],{},"不过在测试和使用的过程中遇到过很多次无法增量编译编辑器的情况，需要对项目进行重新生成。",[11,38,39],{},"目前还不是很确定问题是出在UDeveloperSettings这边还是由于4.18的预览bug引起的。",[11,41,42],{},"类似于这样的定义就可以让配置出现在项目配置中",[44,45,50],"pre",{"className":46,"code":48,"language":49},[47],"language-text","UCLASS(config = ElLog, defaultconfig, meta = (DisplayName = \"ElLog\"))\nclass UElLogSettings : public UDeveloperSettings\n","text",[51,52,48],"code",{"__ignoreMap":53},"",[11,55,56],{},"不过这样的方式有一个缺点，那就是他只能出现在配置的“引擎”分类中，并没有看到能够调整目录的地方。",[27,58,60],{"id":59},"isettingsmodule","ISettingsModule",[11,62,63],{},"其实UE4本身有提供配置的注册接口，只要通过这个接口就能将配置类注册到设定UI中去了：",[44,65,68],{"className":66,"code":67,"language":49},[47],"void RegisterSettings()\n{\n  UE_LOG(LogTemp,Log,TEXT(\"[NS_ELLOG] RegisterSettings()\"));\n  if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr\u003CISettingsModule>(\"Settings\"))\n  {\n    SettingsModule->RegisterSettings(\"Project\", \"Plugins\", \"ELLog\",\n      LOCTEXT(\"TileSetEditorSettingsName\", \"EasyLog Settings\"),\n      LOCTEXT(\"TileSetEditorSettingsDescription\", \"Configure the setting of easylog plugin.\"),\n      GetMutableDefault\u003CUElLogSettings>());\n    UE_LOG(LogTemp, Log, TEXT(\"[NS_ELLOG] RegisterSettings(): Stp\"));\n  }\n}\n\nvoid UnregisterSettings()\n{\n    if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr\u003CISettingsModule>(\"Settings\"))\n    {\n        SettingsModule->UnregisterSettings(\"Project\", \"Plugins\", \"ELLog\");\n    }\n}\n",[51,69,67],{"__ignoreMap":53},[11,71,72],{},"由于这里使用的时候是在插件中，直接在StartupModule()和ShutdownModule()中进行注册和解注册就可以了。",[11,74,75],{},"注意这里的配置是会覆盖的，如果使用了引擎内部相同的配置名称可能会发生奇怪的现象。",[11,77,78],{},"RegisterSettings函数中的各个参数的意义都比较明显，直接看注释就能明白了。",[80,81,82],"blockquote",{},[83,84,85,89,92,95,98,101,104],"ul",{},[86,87,88],"li",{},"@param ContainerName 配置的分类，目前只有Editor和Project两个，分别对应编辑器设置和项目设置两个界面",[86,90,91],{},"@param CategoryName 配置的目录，这个是在上面两种界面中的目录，比如引擎、游戏等。",[86,93,94],{},"@param SectionName 配置的名称，就是显示在左侧目录树上的名称",[86,96,97],{},"@param DisplayName 配置的显示名称",[86,99,100],{},"@param Description 配置的描述",[86,102,103],{},"@param SettingsObject 实际承载这个配置的配置类",[86,105,106],{},"@return 会返回注册后的配置展示类，失败的话会返回Nullptr",[11,108,109],{},"上面的代码注册后就能在项目设置中看到了",[11,111,112],{},[113,114],"img",{"alt":115,"src":116},"image","\u002Fwp-content\u002Fuploads\u002F2017\u002F10\u002Fimage_thumb.png",[11,118,119],{},[113,120],{"alt":115,"src":121},"\u002Fwp-content\u002Fuploads\u002F2017\u002F10\u002Fimage_thumb-1.png",[11,123,124],{},"需要注意的是，ISettingModule这个类型是编辑器使用的，在Shipping模式下无法使用，所以在相关的代码附近注意加上WITH_EDITOR的宏来进行差分。",[11,126,127],{},"通常情况下这样就可以了，不过由于插件的类型原因，这里还是有一个问题。",[27,129,131],{"id":130},"loading-phase","Loading Phase",[11,133,134],{},"UE4中的模块都有载入时机的概念，在uplugin文件中可以进行配置。",[11,136,137],{},"目前可用的载入时机有",[80,139,140,143,146,149,152,155,158],{},[11,141,142],{},"PostConfigInit：引擎初始化阶段，在配置系统初始化完成后",[11,144,145],{},"PreLoadingScreen：引擎初始化阶段，可以在这里挂入LoadingScreen的注册",[11,147,148],{},"PreDefault：引擎初始化阶段，在Default阶段之前",[11,150,151],{},"Default：引擎初始化阶段，此时所有的游戏模块加载已经完成",[11,153,154],{},"PostDefault：引擎初始化阶段，在Default阶段之后",[11,156,157],{},"PostEngineInit：引擎初始化完成后",[11,159,160],{},"None：不会自动加载",[11,162,163],{},"这几个加载阶段有的在文档中描述不是很明确，由于没有实际使用到，所以就没有深入看过。当遇到相应需求的时候，再进行判断比较合适。",[11,165,166],{},"这里由于ELLog本身是Log的插件，所以为了尽可能早的加载完成，就选择了PostConfigInit阶段。",[11,168,169],{},"但是在这个阶段，SettingModule其实并没有完成加载，所以无法成功完成注入到配置系统中的工作。",[11,171,172],{},"因此需要借助额外的引擎接口才行",[44,174,177],{"className":175,"code":176,"language":49},[47],"\u002F\u002FNS_ELLOG::RegisterSettings();\nFCoreDelegates::OnFEngineLoopInitComplete.AddStatic(&NS_ELLOG::RegisterSettings);\n",[51,178,176],{"__ignoreMap":53},[11,180,181],{},"在StartupModule()中不直接进行注册，而是注册到引擎初始化完成的Delegate上，这样就可以在SettingModule加载完成之后执行注册了。",[11,183,184,185,191],{},"以上的代码都可以在",[21,186,190],{"href":187,"rel":188},"https:\u002F\u002Fgithub.com\u002FArisego\u002FELLog",[189],"nofollow","ELLog插件","中找到，因此这里就不多贴代码了。",{"title":53,"searchDepth":193,"depth":194,"links":195},2,3,[196,197,198],{"id":29,"depth":193,"text":30},{"id":59,"depth":193,"text":60},{"id":130,"depth":193,"text":131},"2017-10-14","md",{"layout":202,"status":203,"published":204,"author":205,"author_login":207,"author_email":208,"wordpress_id":209,"wordpress_url":210,"date_gmt":211,"excerpt":212},"post","publish",true,{"display_name":206,"login":207,"email":208,"url":53},"风铃","flinkor","flinkor@foxmail.com",1972,"\u002F\u002F?p=1972","2017-10-14 11:05:31 +0000",{"type":8,"value":213},[214],[11,215,13],{},"\u002F2017-10-14-ue4-config-setting",{"title":6,"description":13},"_legacy\u002F2017\u002F2017-10-14-ue4-config-setting",[220,221,222],"UE4","Config","Setting","vf1l0LywvIQwcofjPXDbGiu2fQQJnhd7FsD0aYqDQKs",{"id":225,"title":226,"body":227,"date":978,"description":231,"extension":200,"meta":979,"navigation":204,"path":988,"seo":989,"stem":990,"tags":991,"__hash__":994},"blogs\u002F_legacy\u002F2017\u002F2017-08-23-ue4-lighting-and-optimize.md","UE4光照及优化",{"type":8,"value":228,"toc":937},[229,232,235,256,259,262,265,270,275,278,281,284,288,291,296,299,302,307,310,313,316,319,322,325,328,331,336,339,342,345,348,356,359,364,367,372,375,379,382,387,390,395,398,401,404,408,411,416,419,422,427,430,433,437,440,443,446,449,454,457,462,466,469,474,477,480,483,487,490,494,497,500,503,512,515,518,523,526,530,533,536,539,545,548,553,556,561,564,569,572,576,579,582,587,590,593,597,600,606,609,615,618,623,626,630,639,642,647,650,653,656,659,663,666,672,675,678,683,686,689,694,697,700,706,710,713,719,722,726,729,735,738,742,745,750,753,756,759,764,768,771,777,780,783,786,790,793,798,801,805,808,814,817,821,824,827,835,839,842,845,848,851,856,859,862,867,870,873,877,880,883,888,891,894,897,900,904,907,912,915,923,928,931,934],[11,230,231],{},"UE4的光照系统很强大，效果也很好，但是在场景复杂度较高或者开放世界的情况下，很容易造成性能瓶颈。",[11,233,234],{},"当前UE4版本为4.17.1。",[11,236,237,238,243,244,249,250,255],{},"光照系统的大部分应用都可以在[",[21,239,242],{"href":240,"rel":241},"https:\u002F\u002Fdocs.unrealengine.com\u002Flatest\u002FCHN\u002FEngine\u002FRendering\u002FLightingAndShadows\u002Findex.html",[189],"官方文档","]中找到，这里的大部分内容是对官方Lighting系列[",[21,245,248],{"href":246,"rel":247},"https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=jCsrWzt9F28",[189],"视频1","][",[21,251,254],{"href":252,"rel":253},"https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=nm1slxtF_qA",[189],"视频2","]的总结。",[27,257,258],{"id":258},"静态光照",[11,260,261],{},"UE4的静态光照是在光照构建中进行预计算的部分，会对预计算的光照结果进行存储，例如光照贴图、阴影贴图这样的形式，可以在运行时支付较低的效率而获得较好的光照结果。",[11,263,264],{},"静态光照可以在世界设置中可以进行关闭",[11,266,267],{},[113,268],{"alt":115,"src":269},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-7.png",[271,272,274],"h3",{"id":273},"lightmass-importance-volume","Lightmass Importance Volume",[11,276,277],{},"这个是预计算光照用的Volume，LightMass的光照计算在点击“构建光照”之后会产生光照贴图。",[11,279,280],{},"控制良好的预计算光照可以让场景变得美观的同时降低动态光照的成本，但是在控制不好的时候就会造成贴图空间爆炸。",[11,282,283],{},"LightMass Importance Volume是用来控制预计算精度的，很明显的一点是，加上之后在空间内部会生成更多的间接光照缓存点，使得间接光照的效果变得更好。",[271,285,287],{"id":286},"ssao","SSAO",[11,289,290],{},"世界设定中还有一个LightMass相关的功能",[11,292,293],{},[113,294],{"alt":115,"src":295},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-8.png",[11,297,298],{},"LightMass这里的AO就是SSAO，由于是工作在屏幕空间的后期计算，要进行探索的话可以在PostProcess中进行调整测试。",[11,300,301],{},"还有一个额外的选项",[11,303,304],{},[113,305],{"alt":115,"src":306},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-9.png",[11,308,309],{},"打开之后可以使得PrecompoutedAOMask材质节点变为有效，这样就可以使用AO的数据来对场景内物体之间的混合效果进行控制。",[11,311,312],{},"详细的可以看这个选项的注释。",[11,314,315],{},"更正：",[11,317,318],{},"这里是错误的，LightMass选项里的AO选项是给预计算光照的，Generate Ambient Occlusion Material这个选项打开的PrecompoutedAOMask也是预计算光照的结果反映到材质中的方式。SSAO是工作在屏幕空间的一种PostProcess效果，与预计算光照是不同的。",[11,320,321],{},"感谢@裕 的指正~",[271,323,324],{"id":324},"间接光照缓存",[11,326,327],{},"间接光照缓存的作用是通过缓存某个点的间接光照，将其作用于经过该处的动态物体上，以获得好的间接光照效果。",[11,329,330],{},"在Movable的物体以及角色上可以对间接光照的计算类型进行设定",[11,332,333],{},[113,334],{"alt":115,"src":335},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-10.png",[11,337,338],{},"ILCQ为Point的时候就是一个点，Volume就是很多点。",[11,340,341],{},"在物体移动时，这些生成的点将根据自己所处的位置，通过周围的间接光照缓存点进行插值并计算出间接光照。",[11,343,344],{},"虽然插值点多的话间接光照效果会变好，但使用何种形式需要根据性能和需求进行权衡。",[11,346,347],{},"可以使用",[80,349,350,353],{},[11,351,352],{},"r.cache.drawinterplotionpoint 1",[11,354,355],{},"r.cache.updateeveryframe 1",[11,357,358],{},"这两条指令来预览缓存插值点的生成。",[11,360,361],{},[113,362],{"alt":115,"src":363},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-11.png",[11,365,366],{},"对于角色的光照缓存还有一个另外的",[11,368,369],{},[113,370],{"alt":115,"src":371},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-12.png",[11,373,374],{},"用于提高区域计算精度的体积。",[271,376,378],{"id":377},"capsule-shadows","Capsule Shadows",[11,380,381],{},"这个是专门为骨骼模型设计的投影优化方式，在骨骼的Lighting属性中能够看到相关的选项：",[11,383,384],{},[113,385],{"alt":115,"src":386},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-13.png",[11,388,389],{},"要使用必须在骨骼网格中指定用于投影的Physics Asset。",[11,391,392],{},[113,393],{"alt":115,"src":394},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-14.png",[11,396,397],{},"使用这种方式可以防止一般较为复杂的角色模型在进行投影计算时产生过多的消耗，尤其是同一个场景内有很多角色模型的情况。",[27,399,400],{"id":400},"光照问题",[11,402,403],{},"在光照的结果上，有时会出现并非预期的结果。在进行场景构建、模型制作时需要预先做好一些预防工作。",[271,405,407],{"id":406},"indirect-seams","Indirect Seams",[11,409,410],{},"间接光照的运算结果在模型之间的接缝处会出现不自然的裂缝",[11,412,413],{},[113,414],{"alt":115,"src":415},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-15.png",[11,417,418],{},"这种的主要原因是两个Mesh之间虽然是平滑的，但是在间接光照进行阴影计算时并不知道这些信息。",[11,420,421],{},"可以通过在世界设置中调节间接光照的质量和平滑度来减少这种现象",[11,423,424],{},[113,425],{"alt":115,"src":426},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-16.png",[11,428,429],{},"提高间接光照质量会加重光照构建的成本，而如果过于提高平滑度的话，会导致间接光照的很多细节被丢弃。",[11,431,432],{},"所以一个更好的解决方案是，在构建关卡时，如果是一个平滑的面的话就直接使用一个整体的模型来做，而不是用好几个模型拼接而成。",[271,434,436],{"id":435},"uv-seams","UV Seams",[11,438,439],{},"这个是由于模型的UV没有很好的接合造成的，由于邻近的顶点在UV上并不连接，在进行间接光照计算时，产生的结果就没有办法很好的利用这些信息。",[11,441,442],{},"根据官方的说明，提高间接光照质量并不会解决UV Seams的问题。",[11,444,445],{},"这个问题更多的是在建模上进行解决。",[11,447,448],{},"不要生成这样的UV",[11,450,451],{},[113,452],{"alt":115,"src":453},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-17.png",[11,455,456],{},"而是尽量保持邻接信息",[11,458,459],{},[113,460],{"alt":115,"src":461},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-18.png",[271,463,465],{"id":464},"bleeding","Bleeding",[11,467,468],{},"光照泄露的主要原因是光照贴图的分辨率造成的",[11,470,471],{},[113,472],{"alt":115,"src":473},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-19.png",[11,475,476],{},"像这样室外的光照感觉上就像直接透过到了室内，显然不符合预期。",[11,478,479],{},"虽然通过修改光照贴图的分辨率来进行应对，但是这样就相当于绕过了问题的来源。",[11,481,482],{},"更根本的解决方法是，让“地板”与房间的尺寸匹配，这样在光照计算时，房间的地板就不会接收到外部的光的光照计算。",[27,484,486],{"id":485},"tips","TIPS",[11,488,489],{},"UE4的光照系统中有一些通用的工具和功能，可以方便的对光照进行布置。",[271,491,493],{"id":492},"lpv","LPV",[11,495,496],{},"Light Propagation Volumes目前处于开发阶段，但是在光照相关的属性的很多部分都能看到它的对应属性。",[11,498,499],{},"这个体积主要的作用是，在动态光照中对间接光照之类的效果进行光线传播运算。",[11,501,502],{},"功能上非常的有用，因为有时候确实会需要在动态光照中有间接光照这样的效果来加强场景的真实性。",[11,504,505,506,511],{},"更多的内容可以参考官方的[",[21,507,510],{"href":508,"rel":509},"https:\u002F\u002Fdocs.unrealengine.com\u002Flatest\u002FCHN\u002FEngine\u002FRendering\u002FLightingAndShadows\u002FLightPropagationVolumes\u002Findex.html",[189],"LPV文档","]。",[11,513,514],{},"这里需要注意的是LPV虽然从命名上看起来像是一个体积控件，但是其实并不存在这样一个Volume，其属性是在PostProcess中进行修改的。",[11,516,517],{},"在开启之后可以在",[11,519,520],{},[113,521],{"alt":115,"src":522},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-20.png",[11,524,525],{},"打开LPV的属性可视化。",[271,527,529],{"id":528},"csm","CSM",[11,531,532],{},"Cascade Shadow Map是UE4阴影贴图的使用方式，在Far Shadow、Dynamic Shadow和Static Shadow中使用了这个机制。",[11,534,535],{},"这个机制的主要作用是，在不同的距离层级，使用不同精度的阴影贴图。",[11,537,538],{},"在设定CSM的同时，还可以对过渡效果进行调节",[11,540,541],{},[113,542],{"alt":543,"src":544},"clip_image00115","\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fclip_image00115_thumb.png",[11,546,547],{},"对应的CSM数量被设置为0的话，就相当于关闭了相应的阴影类型。",[11,549,550],{},[113,551],{"alt":115,"src":552},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-21.png",[11,554,555],{},"CSM的计算范围可以通过在显示中打开",[11,557,558],{},[113,559],{"alt":115,"src":560},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-22.png",[11,562,563],{},"这个选项来进行预览",[11,565,566],{},[113,567],{"alt":115,"src":568},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-23.png",[11,570,571],{},"类似这样，可以在调节相关属性的时候有一个好的可视化工具。",[271,573,575],{"id":574},"emissive-material","Emissive Material",[11,577,578],{},"自发光颜色的材质是通过HDR来实现泛光效果的，因此它本身并不参与光照运算。",[11,580,581],{},"通过在使用了自发光颜色材质的物体上打开",[11,583,584],{},[113,585],{"alt":115,"src":586},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-24.png",[11,588,589],{},"可以让其能够照亮周围环境，但仅限于静态光照。当物体是Movable时，没有办法开启这个选项。",[11,591,592],{},"视频中实现的类型于动态照亮的效果是通过在物体上绑定一个改变GI的PP来实现的，然后两个PP之间的Blending就会改变空间内的灯光造成的影响，形成类似于被物体本身照亮的效果。",[271,594,596],{"id":595},"error-coloring","Error Coloring",[11,598,599],{},"错误着色可以用于排查静态光照计算时报出的UV方面的错误，因为光照构建时只是提示物体上有UV的Overlapping和Wrapping有时候还是很难找到对应的问题的，尤其是模型并不是自己构建的情况下。",[11,601,602],{},[113,603],{"alt":604,"src":605},"clip_image001","\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fclip_image001_thumb.png",[11,607,608],{},"打开这个选项之后要将光照质量调整为预览，才能看到错误着色。",[11,610,611],{},[113,612],{"alt":613,"src":614},"clip_image0015","\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fclip_image0015_thumb.png",[11,616,617],{},"重新构建一次光照，就能看到",[11,619,620],{},[113,621],{"alt":115,"src":622},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-25.png",[11,624,625],{},"橙色的部分是Overlapping而绿色的部分是Wrapping。",[271,627,629],{"id":628},"volumetric-lighting","Volumetric Lighting",[11,631,632,633,638],{},"这是类似于聚光灯的[",[21,634,637],{"href":635,"rel":636},"https:\u002F\u002Fdocs.unrealengine.com\u002Flatest\u002FCHN\u002FEngine\u002FRendering\u002FLightingAndShadows\u002FLightShafts\u002Findex.html",[189],"Light Shaft","]的效果，官方的Blueprint示例工程中也有类似的名为GodRay的效果实现。",[11,640,641],{},"在引擎内容中搜索LightBeam就能找到",[11,643,644],{},[113,645],{"alt":115,"src":646},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-26.png",[11,648,649],{},"这里的模拟方式是在类似光束效果的模型上贴上一个Translucent贴图。",[11,651,652],{},"虽然半透明材质的消耗比普通的材质高，但是在实现光束效果上却是很高的成本节约。",[27,654,655],{"id":655},"动态光照",[11,657,658],{},"动态光照是实时计算的光照，如果关闭了光照预计算的话，所有的光照计算都是实时生成的。如果没有启用LPV的话，静态光照中的间接光照缓存无法使用的情况下，有时候也会造成画面质量的下降。",[271,660,662],{"id":661},"distance-filed","Distance Filed",[11,664,665],{},"距离场在动态光照的优化和填补中有相当大的作用，距离场的基本原理就是在模型的周围向外扩散而成的距离场。",[11,667,668],{},[113,669],{"alt":670,"src":671},"clip_image0017","\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fclip_image0017_thumb.png",[11,673,674],{},"距离场的生成需要在项目设置中进行开启，虽然距离场生成后会产生额外的存储成本，但是可以在动态光照优化中起到很大的作用。",[11,676,677],{},"利用距离场生成的阴影的成本会比动态光照的阴影低很多，通常情况下，将动态光照的作用范围调小",[11,679,680],{},[113,681],{"alt":115,"src":682},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-27.png",[11,684,685],{},"然后在基本上看不到阴影差别的距离上使用距离场生成的阴影进行替代可以很好的降低动态光照对场景的消耗。",[11,687,688],{},"事实是，大部分情况下，动态光照的阴影和距离场的阴影，在中距离上基本上没有什么太大的差别。",[690,691,693],"h4",{"id":692},"distance-field-resolution","Distance field resolution",[11,695,696],{},"Distance field resolution这个属性是用于调整距离场的精细度的，在Mesh自己的设置里面可以找到。",[11,698,699],{},"稍微增加一点就会有明显的提升，重要的是平衡的选择，远距离物体完全没有必要性。",[11,701,702],{},[113,703],{"alt":704,"src":705},"clip_image0019","\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fclip_image0019_thumb.png",[690,707,709],{"id":708},"raytraced-distahcefield-shadows","RayTraced DistahceField Shadows",[11,711,712],{},"对于需要柔和的渐变光照的情况，可以使用",[11,714,715],{},[113,716],{"alt":717,"src":718},"clip_image002","\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fclip_image002_thumb.png",[11,720,721],{},"打开只有在下面的属性可以调节因距离而变化的边缘阴影的效果。",[690,723,725],{"id":724},"selfshadow","SelfShadow",[11,727,728],{},"当物体的自身投影出问题的时候可以试着调节",[11,730,731],{},[113,732],{"alt":733,"src":734},"clip_image003","\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fclip_image003_thumb.png",[11,736,737],{},"来进行修正。",[690,739,741],{"id":740},"two-sided-distance-field-generation","Two-Sided Distance Field Generation",[11,743,744],{},"一般在Foliage上会使用到的属性，如果觉得生成的DF数据形成的投影不够浓密的话，可以打开这个选项。",[11,746,747],{},[113,748],{"alt":115,"src":749},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-28.png",[11,751,752],{},"双面计算会产生额外的成本，在有必要的情况下使用即可，不过也可以考虑使用下面的替代物品。",[690,754,755],{"id":755},"距离场替代物品",[11,757,758],{},"使用一个替代的物品来计算距离场，通常也是在Foliage中使用到，可以降低树的面多造成的性能影响。",[11,760,761],{},[113,762],{"alt":115,"src":763},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-29.png",[271,765,767],{"id":766},"contact-shadow","Contact Shadow",[11,769,770],{},"这个是Light Source中的属性",[11,772,773],{},[113,774],{"alt":775,"src":776},"clip_image00111","\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fclip_image00111_thumb.png",[11,778,779],{},"设置成0以上的值的话就会进行接触阴影的计算，这个计算时工作在屏幕空间的。",[11,781,782],{},"由于是工作在屏幕空间，在物体距离较远时阴影的损失也不会变的严重。",[11,784,785],{},"可以用于填补默认的级联阴影的距离损失，也就是说，可以调低级联阴影，降低阴影消耗。",[271,787,789],{"id":788},"light-function","Light Function",[11,791,792],{},"光照函数相对阴影计算而言的成本是很低的，所以在实现云的投影的时候通常会使用光照函数。",[11,794,795],{},[113,796],{"alt":115,"src":797},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-30.png",[11,799,800],{},"官方的优化建议中也有说明，如果多个组合光源的效果可以用光照函数来替代的话，可以很好的提高效率。",[271,802,804],{"id":803},"distance-filed-ao","Distance Filed AO",[11,806,807],{},"这个是天空光特有的功能，天空光可以利用距离场的生成数据进行环境光的投影计算",[11,809,810],{},[113,811],{"alt":812,"src":813},"clip_image00113","\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fclip_image00113_thumb.png",[11,815,816],{},"只有当天空光是可移动的时候才能使用。",[271,818,820],{"id":819},"ies","IES",[11,822,823],{},"IES的成本比光照函数还低一些，可以实现一些低成本的投影效果。",[11,825,826],{},"有助于关闭不必要的光照投影，例如只是用于模拟灯罩、遮挡的投影，或者干脆是车灯这样的效果。",[11,828,829,830,511],{},"IES的使用可以参照官方的[",[21,831,834],{"href":832,"rel":833},"https:\u002F\u002Fdocs.unrealengine.com\u002Flatest\u002FCHN\u002FEngine\u002FRendering\u002FLightingAndShadows\u002FIESLightProfiles\u002Findex.html",[189],"IES文档",[271,836,838],{"id":837},"far-shadow","Far Shadow",[11,840,841],{},"这是与通常的静态光照和动态光照相反的一种阴影模式，主要是为了保持在远景上的投影来使得场景看起来更有真实感。",[11,843,844],{},"通常在Landscape上开启使用，对于需要的物体，也可以开启使用。注意，要在对应的光源上也开启Far Shadow才行。",[271,846,847],{"id":847},"设置",[11,849,850],{},"在项目设置中个，有一个关闭静态光照的总开关",[11,852,853],{},[113,854],{"alt":115,"src":855},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-31.png",[11,857,858],{},"不过通常在对应的地图的世界设置中进行关闭更加具有可控制性一些。",[11,860,861],{},"还有针对移动端CSM的专有设定",[11,863,864],{},[113,865],{"alt":115,"src":866},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-32.png",[27,868,869],{"id":869},"优化",[11,871,872],{},"UE4提供了一些用于场景优化的工具，像是LOD和Mipmap这样的机制在场景优化的时候就比较实用。",[271,874,876],{"id":875},"cull-distance-volume","Cull Distance Volume",[11,878,879],{},"这个是一个用于裁剪的体积，其内部的物体在远离玩家的时候回直接被裁剪掉，不参与渲染。",[11,881,882],{},"由于动态光照的性能消耗与参与计算的面数成比例，这样就可以起到一定的优化作用了，思路基本和LOD相同。",[11,884,885],{},[113,886],{"alt":115,"src":887},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-33.png",[11,889,890],{},"CullDistance的属性比较简单，每个数组的元素表示的是物体大小小于该值的，应该在里玩家多少距离处隐藏。这里的数据虽然会被按照顺序使用，但是实际上打乱顺序也没有关闭。",[11,892,893],{},"不过有两个问题需要留意",[11,895,896],{},"首先，必须在PIE以上的状态Cull Distance Volume才会起作用。在编辑器内必须按G进入游戏预览模式才能看到效果。",[11,898,899],{},"然后，必须有一个cull distance为0的设置赋给一个大的size，如上面的(1000,0)，否则当距离到达最远的Distance时，会裁剪掉内部的所有物体，包括天空球、大气雾这些实际上没有Size的物体。",[271,901,903],{"id":902},"foliage-culling","Foliage Culling",[11,905,906],{},"Foliage的Culling属性可以在每一个独立的Foliage上进行设置",[11,908,909],{},[113,910],{"alt":115,"src":911},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-34.png",[11,913,914],{},"如上面的Cull Distance设定，在没有使用PerinstanceFadeAmount的情况下，采用的裁剪距离时1000。",[11,916,917,918,922],{},"从500",[919,920,921],"del",{},"1000的范围内PerInstanceFadeAmount由1","0进行变化，这样就可以在材质中对Foliage进行一个Fade的过程，而不是直接突兀的从边界消失。",[11,924,925],{},[113,926],{"alt":115,"src":927},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-35.png",[11,929,930],{},"使用PerInstanceFadeAmount配合Translucent的Mask替代方案DitherTemporalAA，可以实现较好的过渡效果。",[27,932,933],{"id":933},"总结",[11,935,936],{},"光照是渲染中的一个很重要的部分，如果没有处理好的话，不仅场景不好看，还极其的影响效率，是非常需要注意的一个部分。",{"title":53,"searchDepth":193,"depth":194,"links":938},[939,945,950,957,973,977],{"id":258,"depth":193,"text":258,"children":940},[941,942,943,944],{"id":273,"depth":194,"text":274},{"id":286,"depth":194,"text":287},{"id":324,"depth":194,"text":324},{"id":377,"depth":194,"text":378},{"id":400,"depth":193,"text":400,"children":946},[947,948,949],{"id":406,"depth":194,"text":407},{"id":435,"depth":194,"text":436},{"id":464,"depth":194,"text":465},{"id":485,"depth":193,"text":486,"children":951},[952,953,954,955,956],{"id":492,"depth":194,"text":493},{"id":528,"depth":194,"text":529},{"id":574,"depth":194,"text":575},{"id":595,"depth":194,"text":596},{"id":628,"depth":194,"text":629},{"id":655,"depth":193,"text":655,"children":958},[959,967,968,969,970,971,972],{"id":661,"depth":194,"text":662,"children":960},[961,963,964,965,966],{"id":692,"depth":962,"text":693},4,{"id":708,"depth":962,"text":709},{"id":724,"depth":962,"text":725},{"id":740,"depth":962,"text":741},{"id":755,"depth":962,"text":755},{"id":766,"depth":194,"text":767},{"id":788,"depth":194,"text":789},{"id":803,"depth":194,"text":804},{"id":819,"depth":194,"text":820},{"id":837,"depth":194,"text":838},{"id":847,"depth":194,"text":847},{"id":869,"depth":193,"text":869,"children":974},[975,976],{"id":875,"depth":194,"text":876},{"id":902,"depth":194,"text":903},{"id":933,"depth":193,"text":933},"2017-08-23",{"layout":202,"status":203,"published":204,"author":980,"author_login":207,"author_email":208,"wordpress_id":981,"wordpress_url":982,"date_gmt":983,"excerpt":984},{"display_name":206,"login":207,"email":208,"url":53},1952,"\u002F\u002F?p=1952","2017-08-23 07:00:16 +0000",{"type":8,"value":985},[986],[11,987,231],{},"\u002F2017-08-23-ue4-lighting-and-optimize",{"title":226,"description":231},"_legacy\u002F2017\u002F2017-08-23-ue4-lighting-and-optimize",[220,992,993],"Rendering","Lighting","ImEbV9hxl70JgN620bn2U_qJFuejFQ8rUEAkeajNxaU",{"id":996,"title":997,"body":998,"date":1144,"description":1002,"extension":200,"meta":1145,"navigation":204,"path":1154,"seo":1155,"stem":1156,"tags":1157,"__hash__":1158},"blogs\u002F_legacy\u002F2017\u002F2017-08-09-ue4-17-release-review.md","UE4.17新功能探索",{"type":8,"value":999,"toc":1137},[1000,1003,1006,1009,1012,1015,1018,1021,1024,1027,1031,1034,1037,1042,1045,1050,1053,1057,1060,1063,1066,1071,1074,1079,1082,1085,1089,1092,1097,1100,1103,1106,1109,1114,1117,1120,1123,1128,1131,1134],[11,1001,1002],{},"4.17的版本更新已经正式的Release了，虽然之前一直有下载Preview的版本进行测试，却没有什么时间查看新添加的功能呢。",[11,1004,1005],{},"现在官方已经有了正式的Release Note，要看看引擎又添加了什么新功能就变得更简单了呢。",[27,1007,1008],{"id":1008},"概览",[11,1010,1011],{},"这次的主要更新之一时Sequencer，不过遗憾的是并没有真正是使用过Sequencer，所以不是很清楚官方的功能提升到底提升到了什么程度。",[11,1013,1014],{},"大概就是简化和强化操作之类的，Sequencer不仅仅是用来制作过场动画的工具，同时也能制作达到影视级别的CG动画输出。",[11,1016,1017],{},"官方的新声音系统，Unreal Audio依然在制作中。",[11,1019,1020],{},"平台支持上，包括苹果的ARKit和Google的Tango都开始了早期支持。",[11,1022,1023],{},"UMG有了新的旋转剪切系统，不过大概用到的人并不多。而蓝图中现在有了伪节点，这个功能就比较好了，可以防止因为C++代码出现变更而蓝图链接全部断掉，完全不知如何是好的局面出现。现在因为定义变更之类的原因断掉的节点会保留原来的节点，标记为红色。这样就可以按图索骥，依样恢复蓝图的连接了。",[11,1025,1026],{},"同时蓝图的编译有了新的Compile Manager，据说蓝图编译速度加快了50%。",[27,1028,1030],{"id":1029},"vrar","VR\u002FAR",[11,1032,1033],{},"这次的更新中对VR\u002FAR的支持力度变得更大了，比如Sereo Layers现在有了一个平台无关的实现，方便于针对不同VR设备的快速的UI制作。还有诸如VR摄像预览功能之类的。",[11,1035,1036],{},"一个比较大的更新是，现在可以为针对VR游戏的设备设置分屏了，可以让VR头戴设备中的显示与显示器上输出的显示不同。",[11,1038,1039],{},[113,1040],{"alt":115,"src":1041},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb.png",[11,1043,1044],{},"可以通过蓝图函数进行设置控制，据说以后会加入各自的玩家操作支持，使得显示器和VR头盔可以实现”联机”。目前也能看到这样的函数：",[11,1046,1047],{},[113,1048],{"alt":115,"src":1049},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-1.png",[11,1051,1052],{},"由于没有VR设备，无法进行尝试。",[27,1054,1056],{"id":1055},"render","Render",[11,1058,1059],{},"4.17的一个比较期待的更新就是自定义Shader的支持。",[11,1061,1062],{},"虽然官方坚持99.9%的特效都可以通过现有的材质系统来实现，但是对自定义Shader的支持还是到来了。毕竟有时候出于效率和效果的考虑，还是有需要介入到Shader中去的。",[11,1064,1065],{},"自定义Shader的用法ReleaseNote中已经要简要的说明，4.17新推出的",[11,1067,1068],{},[113,1069],{"alt":115,"src":1070},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-2.png",[11,1072,1073],{},"插件中就能看到官方是如何对自定义Shader进行使用的，这个插件也是年初GDC上官方演示的合成特效之一。而其他的合成效果则在",[11,1075,1076],{},[113,1077],{"alt":115,"src":1078},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-3.png",[11,1080,1081],{},"这个插件中。",[11,1083,1084],{},"还有一个将Sequencer输出到图片上然后贴到Camera前方的Image Plate插件，应当是为了方便过场动画的渲染和播放吧。",[27,1086,1088],{"id":1087},"asset-management-framework","Asset Management Framework",[11,1090,1091],{},"4.16就开始的试验性功能，在这个版本进行了进一步的加强。",[11,1093,1094],{},[113,1095],{"alt":115,"src":1096},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-4.png",[11,1098,1099],{},"开放了很多蓝图接口，现在可以自主的对预先定义的资产进行异步加载了。",[11,1101,1102],{},"不会像以前那样需要复杂的编码，而且据说对加载速度的提升也比较明显。",[11,1104,1105],{},"但是打包和资产ID的指定方面可能要到更新的版本才会有变更。",[11,1107,1108],{},"与此同时添加的还有Asset Registry的相关功能的蓝图开放。",[11,1110,1111],{},[113,1112],{"alt":115,"src":1113},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-5.png",[11,1115,1116],{},"这样使用蓝图做编辑器扩展就更方便了……",[27,1118,1119],{"id":1119},"其他",[11,1121,1122],{},"其他的还有Sobol准随机序列的蓝图和材质节点的添加，以及基于贴图的重要度采样功能：",[11,1124,1125],{},[113,1126],{"alt":115,"src":1127},"\u002Fwp-content\u002Fuploads\u002F2017\u002F08\u002Fimage_thumb-6.png",[11,1129,1130],{},"以及很多新的功能和改进。",[11,1132,1133],{},"其中有一个比较有用的功能是实例化材质的烘焙。",[11,1135,1136],{},"可以将复杂的材质节点烘焙成简单的材质，有效的降低渲染消耗。",{"title":53,"searchDepth":193,"depth":194,"links":1138},[1139,1140,1141,1142,1143],{"id":1008,"depth":193,"text":1008},{"id":1029,"depth":193,"text":1030},{"id":1055,"depth":193,"text":1056},{"id":1087,"depth":193,"text":1088},{"id":1119,"depth":193,"text":1119},"2017-08-09",{"layout":202,"status":203,"published":204,"author":1146,"author_login":207,"author_email":208,"wordpress_id":1147,"wordpress_url":1148,"date_gmt":1149,"excerpt":1150},{"display_name":206,"login":207,"email":208,"url":53},1871,"\u002F\u002F?p=1871","2017-08-09 13:36:58 +0000",{"type":8,"value":1151},[1152],[11,1153,1002],{},"\u002F2017-08-09-ue4-17-release-review",{"title":997,"description":1002},"_legacy\u002F2017\u002F2017-08-09-ue4-17-release-review",[220],"uMCZJKl2CAdmMSZNqSjsiRcHTFhKh8HppZXTv_Y2-Ew",{"id":1160,"title":1161,"body":1162,"date":1817,"description":1166,"extension":200,"meta":1818,"navigation":204,"path":1827,"seo":1828,"stem":1829,"tags":1830,"__hash__":1831},"blogs\u002F_legacy\u002F2017\u002F2017-07-30-ue4-profiling-preview.md","初探UE4中的Profiling",{"type":8,"value":1163,"toc":1773},[1164,1167,1170,1184,1187,1191,1194,1199,1202,1205,1208,1213,1216,1223,1227,1230,1233,1236,1239,1242,1246,1251,1254,1257,1260,1263,1266,1269,1273,1276,1281,1284,1288,1291,1296,1300,1303,1308,1312,1320,1326,1329,1332,1335,1339,1342,1345,1348,1351,1356,1359,1364,1367,1393,1401,1404,1409,1413,1416,1419,1422,1425,1428,1432,1435,1438,1443,1446,1451,1454,1460,1463,1466,1469,1474,1477,1480,1483,1486,1489,1492,1495,1498,1501,1505,1508,1511,1514,1518,1521,1524,1527,1531,1534,1538,1544,1547,1550,1553,1556,1561,1564,1567,1570,1573,1577,1580,1586,1591,1599,1602,1606,1609,1612,1615,1619,1622,1625,1629,1632,1638,1641,1647,1650,1654,1657,1660,1664,1667,1670,1673,1676,1679,1686,1689,1692,1694,1698,1701,1704,1708,1711,1715,1718,1721,1724,1727,1731,1734,1737,1741,1744,1747,1750,1753,1756,1759,1762,1765,1767,1770],[11,1165,1166],{},"Profililng是成品制作过程中非常重要的一个步骤，通过Profiling才能提高运行效率使得作品达到用户能够运行从程度。",[11,1168,1169],{},"UE4本身有提供用于Profiling的工具，但是要正确的将其用于优化却需要经过一些学习。在掌握基础之后，要很好的完成优化，需要的是更多的实践所累积的经验了。",[11,1171,1172,1173,1178,1179,511],{},"本文的主要内容来自对Tech Art Aid的[",[21,1174,1177],{"href":1175,"rel":1176},"https:\u002F\u002Fwww.youtube.com\u002Fplaylist?list=PLF8ktr3i-U4A7vuQ6TXPr3f-bhmy6xM3S",[189],"Profiling系列视频","]的总结和官方的[",[21,1180,1183],{"href":1181,"rel":1182},"https:\u002F\u002Fdocs.unrealengine.com\u002Flatest\u002FCHN\u002FEngine\u002FPerformance\u002Findex.html",[189],"性能分析文档",[11,1185,1186],{},"不过由于Profiling本身的覆盖范围较广，所以这里也只是记录刚刚开始接触的内容。同时，由于并没有很深入的了解过渲染相关的知识，文中有的术语可能存在翻译不正确的现象：D",[27,1188,1190],{"id":1189},"scalability","Scalability",[11,1192,1193],{},"UE4中有提供所谓的可延展性功能，这个功能可以用于快速的调整引擎的工作性能-效率平衡。",[11,1195,1196],{},[113,1197],{"alt":115,"src":1198},"\u002Fwp-content\u002Fuploads\u002F2017\u002F07\u002Fimage_thumb.png",[11,1200,1201],{},"但是这个功能并不是为优化而设计的，虽然其中使用到的一些设置可以用于优化，但是Scalability本身更多的是为了让开发者为用户提供一个快速的配置。",[11,1203,1204],{},"通常在游戏配置界面中能够看到的配置就是从Scalability入手的。",[11,1206,1207],{},"可以在蓝图中看到一些类似这样的函数",[11,1209,1210],{},[113,1211],{"alt":115,"src":1212},"\u002Fwp-content\u002Fuploads\u002F2017\u002F07\u002Fimage_thumb-1.png",[11,1214,1215],{},"社区中也有共享简单的游戏配置的实现，在设置窗口中可以对不同的渲染等级进行预览，以评估游戏在目标渲染等级上的表现。",[11,1217,1218,1219,511],{},"更多的关于Scalability的内容可以参考[",[21,1220,242],{"href":1221,"rel":1222},"https:\u002F\u002Fdocs.unrealengine.com\u002Flatest\u002FCHN\u002FEngine\u002FPerformance\u002FScalability\u002Findex.html",[189],[27,1224,1226],{"id":1225},"profiling","Profiling",[11,1228,1229],{},"通常性的优化目标就是提高帧率，降低每帧消耗时间。由于现代的CPU通常比较强大，只要不是在游戏逻辑中进行复制的物理模拟或者高强度的AI逻辑运算，性能的瓶颈都会出在与渲染相关的地方。",[11,1231,1232],{},"在进行优化的时候需要注意的是，要在项目配置中关闭Smooth Frame Rate，否则没有办法很好的对性能进行分析。对于打包优化，官方的建议是至少在Development以上的级别下进行，因为Debug下有很多东西非常的影响性能。",[11,1234,1235],{},"同时关闭垂直同步在某些情况下也是必要的，使用r.VSync指令就可以了，在打包版本中也可以使用命令行参数-NoVSync。",[271,1237,1238],{"id":1238},"常用指令",[11,1240,1241],{},"官方的stat指令集中提供了大量的用于性能优化的指令，其中比较常用的是通用的问题定位指令，在找到性能瓶颈之后，可以进一步的使用相关的指令进行问题的查看。",[690,1243,1245],{"id":1244},"stat-unit","stat unit",[11,1247,1248],{},[113,1249],{"alt":115,"src":1250},"\u002Fwp-content\u002Fuploads\u002F2017\u002F07\u002Fimage_thumb-2.png",[11,1252,1253],{},"使用stat unit就可以粗略的对问题的来源进行定位。",[11,1255,1256],{},"为了差分渲染与游戏逻辑的性能消耗，可以通过r.SetRes或者r.ScreenPercentage来有效的降低渲染消耗来辅助定位。",[11,1258,1259],{},"这里面Frame与stat fps输出的帧时间是一样的，其他的三项则对应不同的性能瓶颈：",[11,1261,1262],{},"Game为CPU游戏线程，如果是这里有问题的话通常就是游戏逻辑本身设计太消耗性能了。",[11,1264,1265],{},"Draw为CPU渲染线程，这里是负责向GPU发送DrawCall的，已经是渲染相关的优化。",[11,1267,1268],{},"GPU就是GPU的帧时间了，完全的渲染相关。",[690,1270,1272],{"id":1271},"stat-scenerendering","stat SceneRendering",[11,1274,1275],{},"指令可以用于更加详细的对性能瓶颈进行分析",[11,1277,1278],{},[113,1279],{"alt":115,"src":1280},"\u002Fwp-content\u002Fuploads\u002F2017\u002F07\u002Fimage_thumb-3.png",[11,1282,1283],{},"通过寻找性能消耗较大的pass，对其进行针对性的优化就好了。",[690,1285,1287],{"id":1286},"stat-gpu","stat gpu",[11,1289,1290],{},"则可以用于查看gpu上的性能消耗比例",[11,1292,1293],{},[113,1294],{"alt":115,"src":1295},"\u002Fwp-content\u002Fuploads\u002F2017\u002F07\u002Fimage_thumb-4.png",[690,1297,1299],{"id":1298},"startfirestat-stopfile","StartFire\u002Fstat stopfile",[11,1301,1302],{},"这组指令可以将性能分析文件生成到Saved\u002FProfiling文件夹中。这些文件可以使用Front End中的分析器进行加载并分析：",[11,1304,1305],{},[113,1306],{"alt":115,"src":1307},"\u002Fwp-content\u002Fuploads\u002F2017\u002F07\u002Fimage_thumb-5.png",[690,1309,1311],{"id":1310},"gpu-visualizer","GPU Visualizer",[11,1313,1314,1315,1319],{},"在优化中最常使用的工具还是GPU Visualizer，按快捷键",[1316,1317,1318],"span",{},"Ctrl+Shift+,","就会出来了。",[11,1321,1322],{},[113,1323],{"alt":1324,"src":1325},"SNAGHTMLbe577a","\u002Fwp-content\u002Fuploads\u002F2017\u002F07\u002FSNAGHTMLbe577a_thumb.png",[11,1327,1328],{},"性能优化从这里入手的话就比较直观一些。",[271,1330,1331],{"id":1331},"渲染优化",[11,1333,1334],{},"渲染上会产生的瓶颈通常分为三大类别，Pixel-bound、Vertex-bound、Memory-bound。",[690,1336,1338],{"id":1337},"pixel-bound","Pixel-bound",[11,1340,1341],{},"Translucent的材质物体的大规模使用，半透明粒子都会导致在像素渲染级别上出现瓶颈。",[11,1343,1344],{},"在材质的使用上，Opaque的性能是最高的，因为可以有效的进行Z-buffer裁剪，其次是Masked材质，性能消耗最高的是Translucent。尤其是场景内出现大规模的半透明物体叠加的时候，就会产生大量的绘制负担。",[11,1346,1347],{},"在场景布局上，利用Opaque的物体进行遮蔽，尽量的避免镜头内出现大量半透明物体，有效的利用LOD都是非常重要的。",[11,1349,1350],{},"还有一个方面就是Quad Overdraw，这个似乎是由于GPU的渲染机制引起的，直接引用视频中看到的图片：",[11,1352,1353],{},[113,1354],{"alt":604,"src":1355},"\u002Fwp-content\u002Fuploads\u002F2017\u002F07\u002Fclip_image001_thumb.png",[11,1357,1358],{},"在优化上，要尽量避免屏幕空间内出现小而长的三角形，将其分割为更多的三角形反而更加有效。同时，将屏幕内足够小的物体进行LOD，也可以有效的避免性能消耗。对于Foliage上的叶子，可以使用Particle Trimming来避免过度绘制，据说Speed Tree是自带这个功能的，不过由于没有使用过所以无法确认。particle trimming如其名，在粒子的优化中也有作用。",[11,1360,1361],{},[113,1362],{"alt":115,"src":1363},"\u002Fwp-content\u002Fuploads\u002F2017\u002F07\u002Fimage_thumb-6.png",[11,1365,1366],{},"不过没有实际使用过这个功能，按照介绍的话，性能提升还是比较明显的：",[80,1368,1369,1372,1375,1378,1381,1384,1387,1390],{},[11,1370,1371],{},"Original: 100%",[11,1373,1374],{},"Aligned rect: 69.23%",[11,1376,1377],{},"Optimized 3 verts: 70.66%",[11,1379,1380],{},"Optimized 4 verts: 60.16%",[11,1382,1383],{},"Optimized 5 verts: 55.60%",[11,1385,1386],{},"Optimized 6 verts: 53.94%",[11,1388,1389],{},"Optimized 7 verts: 52.31%",[11,1391,1392],{},"Optimized 8 verts: 51.90%",[11,1394,1395,1396,511],{},"这个数据来自于[",[21,1397,1400],{"href":1398,"rel":1399},"http:\u002F\u002Fwww.humus.name\u002Findex.php?page=Comments&ID=266",[189],"这里",[11,1402,1403],{},"Quared OverDraw可以通过调整为检查模式来对场景中的物体进行检查",[11,1405,1406],{},[113,1407],{"alt":115,"src":1408},"\u002Fwp-content\u002Fuploads\u002F2017\u002F07\u002Fimage_thumb-7.png",[690,1410,1412],{"id":1411},"vertex-bound","Vertex-bound",[11,1414,1415],{},"通常受到影响的就是场景中三角形的数量，如果印象没有错的话，当前UE4内部所有的面应该都是三角形的。会在这里产生瓶颈的还有阴影投射与曲面细分，关于曲面细分，官方有建议是尽量不要使用，在建模阶段直接进行细分是更加具有效率的。",[11,1417,1418],{},"UV Seam和Hard Edges会额外的增加计算的顶点计算的负担，要尽量避免减少使用的频度。",[11,1420,1421],{},"同时Morph Target与WolrdPostionOffset也会产生更多的顶点计算，Skinned Mesh也是如此，不过这些方面，除了WorldPostionOffset可以尽量避免使用之外，只能从游戏逻辑本身的设计上入手了呢。",[11,1423,1424],{},"如果有使用LandScape的话，尽量减少LandScape的面数可以很好的提高性能。",[11,1426,1427],{},"为了避免过量的顶点计算负担，对于远景物体尽量使用BillBoard或者Imposter meshes、Skyboxe texture来代替3D物体。",[690,1429,1431],{"id":1430},"memory-bound","Memory-bound",[11,1433,1434],{},"如果有大量的材质使用了不同的贴图，导致Texture Sample的数量爆炸的话，就会自然的变成瓶颈。",[11,1436,1437],{},"UE4有使用Texture Streaming，如果存储空间爆炸了的话，就会出现贴图模糊的情况，这时候可以使用Stat Streaming指令进行分析。",[11,1439,1440],{},[113,1441],{"alt":115,"src":1442},"\u002Fwp-content\u002Fuploads\u002F2017\u002F07\u002Fimage_thumb-8.png",[11,1444,1445],{},"对于使用相同的材质的情况，可以通过材质中的设定让他们共享Texture。同时在材质中启用GPU本身支持的压缩可以有效的减少存储空间的占用，尽量的使用Texture Packing也是非常的重要的。载入的时候尽量使用Mip级别较低的图片，可以有效的减少存储占用。在材质的贴图使用中，尽量的进行优化的配置也非常的重要。",[11,1447,1448],{},[113,1449],{"alt":115,"src":1450},"\u002Fwp-content\u002Fuploads\u002F2017\u002F07\u002Fimage_thumb-9.png",[11,1452,1453],{},"对于不需要太精细的贴图可以限制其最大尺寸",[11,1455,1456],{},[113,1457],{"alt":1458,"src":1459},"clip_image0014","\u002Fwp-content\u002Fuploads\u002F2017\u002F07\u002Fclip_image0014_thumb.png",[11,1461,1462],{},"另外，光照贴图等也是被算作贴图占用存储空间的，因此也有在这里产生瓶颈的可能性。因此尽量的调低光照贴图的分辨率可以很好的提高性能。",[11,1464,1465],{},"使用Alt+0\u002FLight Map Density可以对场景中的光照贴图密度进行分析。",[11,1467,1468],{},"在窗口>统计总也能进一步的对当前的存储使用状况进行分析",[11,1470,1471],{},[113,1472],{"alt":115,"src":1473},"\u002Fwp-content\u002Fuploads\u002F2017\u002F07\u002Fimage_thumb-10.png",[690,1475,1476],{"id":1476},"前向渲染与延迟渲染",[11,1478,1479],{},"UE4面向VR可以区分前向渲染与延迟渲染，两方各有优劣，在优化上也会有所不同。引擎采用的前向渲染方式是Cluster Forward Shading(Forward+)，详细的技术细节并没有关注过，不过通常前向渲染的光照计算成本会高些，尤其是光照数量较多时会产生明显的性能下降。",[11,1481,1482],{},"使用缓存区可视化功能，可以对延迟渲染使用的缓存进行查看。",[27,1484,1485],{"id":1485},"按通道优化",[11,1487,1488],{},"优化的过程，通常是在玩家通常的地点放置观察摄像，然后通过这个固定点使用GPU Visualizer进行优化。",[11,1490,1491],{},"在使用GPU Visualizer时，会看到各个通道的性能消耗比例，这样就可以针对不同的通道进行优化了。",[11,1493,1494],{},"在打包模式下按下GPU Visualizer后，不会出现界面，但是相关数据会被记录到Log中。",[11,1496,1497],{},"在GPU Visualizer中对帧时间消耗进行排序可以帮助快速找到当前消耗的瓶颈，不过有的pass的消耗可能是不得已的，这里大概就是需要经验的地方了。pass根据工作方式大体上分别工作于屏幕空间和运算空间，像是PostProcess这样的后期处理以及延迟渲染的光照都是工作在屏幕空间的。而像是Z-Buffer的生成这一类的操作则是通过运算空间进行的。一般工作在屏幕空间的通道受到渲染分辨率的影响就会比较大，例如SSAO、AA等。而在运算空间的Pass就会受到Mesh的数量、面数、shader的复杂度的影响。",[271,1499,1500],{"id":1500},"光照",[690,1502,1504],{"id":1503},"lightcompositiontasks_prelighting","LightCompositionTasks_PreLighting",[11,1506,1507],{},"这个通道被SSAO以及非D-Buffer类型的Decals使用。",[11,1509,1510],{},"这里的性能消耗在屏幕空间上，通过在PostProcess中降低AO的半径和消退距离可以减少其产生的运算负担。",[11,1512,1513],{},"同时，非D-Buffer类的Decals也会对其产生影响。",[690,1515,1517],{"id":1516},"composition-after-lighting","Composition After Lighting",[11,1519,1520],{},"只影响Subsurface Profile的Shading Model的SSS效果的通道。",[11,1522,1523],{},"由于工作于屏幕空间，减少其在屏幕中的占比就可以有效的减少消耗。比如使用LOD之类的。",[11,1525,1526],{},"使用Subsurface的Shading Model或者Matcap之类的来进行替代也可以降低这里的消耗。",[690,1528,1530],{"id":1529},"compute-light-grid","Compute Light Grid",[11,1532,1533],{},"用于计算光照相关性的pass，减少动态光照的数量就可以减低消耗。",[690,1535,1537],{"id":1536},"lights","Lights",[11,1539,1540],{},[113,1541],{"alt":1542,"src":1543},"clip_image0016","\u002Fwp-content\u002Fuploads\u002F2017\u002F07\u002Fclip_image0016_thumb.png",[11,1545,1546],{},"延迟渲染的光照是基于DBuffer在屏幕空间呢进行演算的，因此受屏幕分辨率的影响也比较大。",[11,1548,1549],{},"无论是静态光照还是动态光照，都会受到光照本身的数量以及范围的影响。",[11,1551,1552],{},"而动态光照的效率额外的受到光照影响到的面数的影响。",[11,1554,1555],{},"光照的优化应该尽量的减少光照范围的重叠，避免大范围的动态光照，关闭没有太大必要性物体的动态阴影投射。光照的重叠等的查看可以通过调整视图",[11,1557,1558],{},[113,1559],{"alt":115,"src":1560},"\u002Fwp-content\u002Fuploads\u002F2017\u002F07\u002Fimage_thumb-11.png",[11,1562,1563],{},"来进行有效的排查。",[11,1565,1566],{},"光照类型的性能消耗是点光源>直线光源>聚光灯，在使用光照时，如果能用IES或者光照函数进行替代的话，不要使用很多个光源组合成类似的效果。",[11,1568,1569],{},"同时光照函数通常的性能消耗大于IES，其消耗受到光照材质本身的复杂度的影响比较大。",[11,1571,1572],{},"在对光照范围进行优化时，可以通过关闭Use Inverse Squared Falloff，并自己设置Light Falloff Exponent来达到减小光照范围达到类似光照效果。",[690,1574,1576],{"id":1575},"filter-translucent-volume","Filter Translucent Volume",[11,1578,1579],{},"这是半透明物体的光照计算时会用到的pass",[11,1581,1582],{},[113,1583],{"alt":1584,"src":1585},"clip_image0018","\u002Fwp-content\u002Fuploads\u002F2017\u002F07\u002Fclip_image0018_thumb.png",[80,1587,1588],{},[11,1589,1590],{},"带光照的半透明物体的光照大多数来源于一系列面向视锥体的cascade处理过的体积贴图。 这样在体积内的任意点，光照均为单次，但缺点就是体积贴图的分辨率比较低，而且从观察者角度来说，只涵盖了有限的深度范围。",[11,1592,1593,1594,511],{},"详细的说明可以参考官方文档：[",[21,1595,1598],{"href":1596,"rel":1597},"https:\u002F\u002Fdocs.unrealengine.com\u002Flatest\u002FCHN\u002FEngine\u002FRendering\u002FLightingAndShadows\u002FLitTranslucency\u002Findex.html",[189],"带光照的半透明物体",[11,1600,1601],{},"这里产生了瓶颈的话要检查光照的数目、范围和影响到的物体的数量。",[690,1603,1605],{"id":1604},"shadowdepths","ShadowDepths",[11,1607,1608],{},"这个生成通过光源进行阴影投射的深度数据的pass。",[11,1610,1611],{},"作用与这里的消耗主要受到开启了投影的光的数目、动态光照影响的面数、以及阴影的质量的影响。",[11,1613,1614],{},"阴影的质量可以通过Sg.shadow quality进行全局的调节。",[690,1616,1618],{"id":1617},"shadow-projection","Shadow Projection",[11,1620,1621],{},"实际的阴影投射，工作于屏幕空间，所以受分辨率影响，同时也会受到投影的光照数量和范围的影响。",[271,1623,1624],{"id":1624},"基础通道",[690,1626,1628],{"id":1627},"prepass-dom_","PrePass DOM_",[11,1630,1631],{},"EarlyZPass，对非透明物体进行的早期的深度计算。",[11,1633,1634],{},[113,1635],{"alt":1636,"src":1637},"clip_image00110","\u002Fwp-content\u002Fuploads\u002F2017\u002F07\u002Fclip_image00110_thumb.png",[11,1639,1640],{},"数据似乎被用于遮蔽计算，如果不使用Dbuffer Decals的话可以关掉。虽然视频中是这样建议的，但是早期的深度计算可以在BasePass之前进行遮蔽计算，能让basepass以及之后所有的通道的计算减少很多。而且即便在这里不进行深度计算，会影响这里的运算量的变量依然会作用与后面的深度计算阶段，因此关闭EarlyZPass还是需要多做考虑的。另外要使用DBuffer Decals的话必须使用Opaque and masked的zpass计算，否则应该会出现奇怪的现象。",[11,1642,1643],{},[113,1644],{"alt":1645,"src":1646},"clip_image00112","\u002Fwp-content\u002Fuploads\u002F2017\u002F07\u002Fclip_image00112_thumb.png",[11,1648,1649],{},"性能上受到非透明物体的面数的影响，同时根据上面的选项不同也受到Masked的材质的影响。",[690,1651,1653],{"id":1652},"hzb","HZB",[11,1655,1656],{},"Hierarchical Z-Buffer，用于计算HZB遮蔽，同时也会被屏幕空间内的射线演算使用，例如屏幕空间反射计算、AO等。同时被用于Mip的设置。",[11,1658,1659],{},"受屏幕空间的大小影响。据官方描述，HZB拥有较高的固定性能消耗，每个物体所造成的消耗较小。可以通过r.HZBOcclusion来调整运算的类型。",[690,1661,1663],{"id":1662},"base-pass","Base Pass",[11,1665,1666],{},"对非透明的物体进行演算并填充到GBuffer，使用缓冲区可视化模式可以在视图中看到效果。几乎所有的延迟渲染都受到其影响，因此才叫基础通道。",[11,1668,1669],{},"其计算结果包括base color, metallic, specular, roughness, normal, sss profile，并且Decals、Fog以及Velocity的计算也在此处。",[11,1671,1672],{},"其开销受到屏幕空间尺寸、物体数量、面数、Decals的数量、Shader的复杂度，生成的过程中包含光照贴图的推送，因此也会受到光照贴图的大小的影响。",[11,1674,1675],{},"可以通过Stat rhi指令检查各种贴图和triangle的消耗。",[11,1677,1678],{},"另外，前向渲染的光照也在这里进行，此时光照的数量也会影响到这里的消耗。",[690,1680,1682],{"id":1681},"translucency",[1683,1684,1685],"strong",{},"Translucency",[11,1687,1688],{},"半透明的材质以及光照演算，通过Stat gpu中的Translucency and Translucent Lighting可以进一步查看。",[11,1690,1691],{},"消耗受到屏幕空间大小以及屏幕内的半透明物体的数量影响，半透明物体的光照计算要尽量减少过度绘制。以及避免过多的需要进行半透明光照计算的光的数量。",[271,1693,1119],{"id":1119},[690,1695,1697],{"id":1696},"particle-simulationinjection","Particle Simulation\u002FInjection",[11,1699,1700],{},"粒子模拟，这里只展示GPU粒子的消耗，性能主要受粒子数量以及是否开启了基于深度的粒子碰撞影响。",[11,1702,1703],{},"粒子的优化主要通过LOD以及设计上的优化进行。",[690,1705,1707],{"id":1706},"post-process","Post process",[11,1709,1710],{},"UE4的后期处理功能比较多，AA、DOF、自动曝光以及很多其他的功能都在其中。每种PP特效都会产生额外的性能消耗，如果使用了PP材质的话，其复杂度也会影响性能。",[690,1712,1714],{"id":1713},"relection-envirionment","Relection Envirionment",[11,1716,1717],{},"反射捕捉控件的计算缓存",[11,1719,1720],{},"可以将显示模式调整为Reflections来查看各个控件对缓存的影响",[11,1722,1723],{},"通常的建议是，放一个大范围的低精度反射捕捉，然后在需要的地方尽量不重叠的放置高精度的捕捉控件。",[11,1725,1726],{},"影响性能的主要就是捕捉控件的数量及范围，也受屏幕空间的大小影响。",[690,1728,1730],{"id":1729},"render-velocities","Render Velocities",[11,1732,1733],{},"速度主要用于TAA以及Motion Blur，受到移动物体的数量以及其面数的影响。",[11,1735,1736],{},"主要的优化策略是使用LOD。",[690,1738,1740],{"id":1739},"screen-space-reflections","Screen Space Reflections",[11,1742,1743],{},"屏幕空间反射通过以下连个指令来进行调节：",[11,1745,1746],{},"r.ssr.maxroughness 0.0-1.0",[11,1748,1749],{},"r.ssr.quality 0..4",[11,1751,1752],{},"其中Maximum roughness决定着计算的范围的大小。",[27,1754,1755],{"id":1755},"第三方工具",[11,1757,1758],{},"要使用第三方工具进行Profiling，一般需要打包。在进行捕捉之前，打开Toggle draw event的话可以让UE4提供更多的信息给第三方Profiling工具，捕捉完之后则使用同一个命令关闭就好。",[11,1760,1761],{},"第三方工具有Intel的GraphicsPerformance Analyzers、AMD的GPU PerfStudio以及开源的RenderDoc等。",[11,1763,1764],{},"使用第三方工具可以提供一些在硬件层次上获得的细节，在使用UE4本身的Profiling工具无法定位问题时可以进行尝试。",[27,1766,933],{"id":933},[11,1768,1769],{},"总体而言，Profiling是一个复杂的过程。由于是面向最终用户的，需要花费很多精力在上面。",[11,1771,1772],{},"通常的策略包括LOD、裁剪、避免重叠以及低性能的近似替代等，很多的问题还需要在实践中才能发现和解决。",{"title":53,"searchDepth":193,"depth":194,"links":1774},[1775,1776,1791,1815,1816],{"id":1189,"depth":193,"text":1190},{"id":1225,"depth":193,"text":1226,"children":1777},[1778,1785],{"id":1238,"depth":194,"text":1238,"children":1779},[1780,1781,1782,1783,1784],{"id":1244,"depth":962,"text":1245},{"id":1271,"depth":962,"text":1272},{"id":1286,"depth":962,"text":1287},{"id":1298,"depth":962,"text":1299},{"id":1310,"depth":962,"text":1311},{"id":1331,"depth":194,"text":1331,"children":1786},[1787,1788,1789,1790],{"id":1337,"depth":962,"text":1338},{"id":1411,"depth":962,"text":1412},{"id":1430,"depth":962,"text":1431},{"id":1476,"depth":962,"text":1476},{"id":1485,"depth":193,"text":1485,"children":1792},[1793,1802,1808],{"id":1500,"depth":194,"text":1500,"children":1794},[1795,1796,1797,1798,1799,1800,1801],{"id":1503,"depth":962,"text":1504},{"id":1516,"depth":962,"text":1517},{"id":1529,"depth":962,"text":1530},{"id":1536,"depth":962,"text":1537},{"id":1575,"depth":962,"text":1576},{"id":1604,"depth":962,"text":1605},{"id":1617,"depth":962,"text":1618},{"id":1624,"depth":194,"text":1624,"children":1803},[1804,1805,1806,1807],{"id":1627,"depth":962,"text":1628},{"id":1652,"depth":962,"text":1653},{"id":1662,"depth":962,"text":1663},{"id":1681,"depth":962,"text":1685},{"id":1119,"depth":194,"text":1119,"children":1809},[1810,1811,1812,1813,1814],{"id":1696,"depth":962,"text":1697},{"id":1706,"depth":962,"text":1707},{"id":1713,"depth":962,"text":1714},{"id":1729,"depth":962,"text":1730},{"id":1739,"depth":962,"text":1740},{"id":1755,"depth":193,"text":1755},{"id":933,"depth":193,"text":933},"2017-07-30",{"layout":202,"status":203,"published":204,"author":1819,"author_login":207,"author_email":208,"wordpress_id":1820,"wordpress_url":1821,"date_gmt":1822,"excerpt":1823},{"display_name":206,"login":207,"email":208,"url":53},1845,"\u002F\u002F?p=1845","2017-07-30 08:10:34 +0000",{"type":8,"value":1824},[1825],[11,1826,1166],{},"\u002F2017-07-30-ue4-profiling-preview",{"title":1161,"description":1166},"_legacy\u002F2017\u002F2017-07-30-ue4-profiling-preview",[220,1226],"WoD3ma-Xm1UBlc5-o8OYia9aLOKDskWvsGgKObwEBA0",{"id":1833,"title":1834,"body":1835,"date":1939,"description":1839,"extension":200,"meta":1940,"navigation":204,"path":1949,"seo":1950,"stem":1951,"tags":1952,"__hash__":1954},"blogs\u002F_legacy\u002F2017\u002F2017-06-24-ue4-compile-errors-log.md","UE4错误笔记",{"type":8,"value":1836,"toc":1934},[1837,1840,1843,1847,1850,1853,1858,1861,1864,1869,1872,1877,1881,1884,1892,1895,1898,1904,1908,1911,1916,1925,1928],[11,1838,1839],{},"记录了最近遇到的几个编译错误。",[11,1841,1842],{},"当前使用的UE4版本为4.15.3。",[27,1844,1846],{"id":1845},"c4530","C4530",[11,1848,1849],{},"这个错误是尝试在UE4中使用Try\u002FExcept引起的。",[11,1851,1852],{},"报错如下：",[80,1854,1855],{},[11,1856,1857],{},"warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify \u002FEHsc",[11,1859,1860],{},"UE4默认的情况下不允许使用Exception。",[11,1862,1863],{},"AnswerHub有回答说要在build.cs中设置：",[80,1865,1866],{},[11,1867,1868],{},"UEBuildConfiguration.bForceEnableExceptions = true;",[11,1870,1871],{},"但是由于新版本的变更，这个属性变成只读了，现在需要这样设置：",[80,1873,1874],{},[11,1875,1876],{},"bEnableExceptions = true;",[27,1878,1880],{"id":1879},"c2039","C2039",[11,1882,1883],{},"某种意义上的老朋友，报错如下：",[80,1885,1886,1889],{},[11,1887,1888],{},"1>E:\\UEPro\\New_UI\\Plugins\\EasyLog\\Source\\EasyLog\\Private\\LogHolder.cpp(28): error C2039: “CreateDirectoryW”: 不是“IPlatformFile”的成员",[11,1890,1891],{},"1> f:\\epic\\ue_4.15\\engine\\source\\runtime\\core\\public\\GenericPlatform\u002FGenericPlatformFile.h(160): note: 参见“IPlatformFile”的声明",[11,1893,1894],{},"UE4中这种错误报进引擎内部的，一般都是因为定义冲突引起的，需要针对包含关系进行排查。",[11,1896,1897],{},"这种与Win Api相关的，通常是由于UE4中对Windows.h的兼容引起的。有时也会报出DWORD未定义这样的错误。可以尝试使用引擎提供的帮助包含：",[44,1899,1902],{"className":1900,"code":1901,"language":49},[47],"#include \"AllowWindowsPlatformTypes.h\"\n\n#include \"something_about_windows.h\"\n\n#include \"HideWindowsPlatformTypes.h\"\n",[51,1903,1901],{"__ignoreMap":53},[27,1905,1907],{"id":1906},"c4596","C4596",[11,1909,1910],{},"这个错误其实是VS2017的版本更新的新功能造成的，报错如下：",[80,1912,1913],{},[11,1914,1915],{},"error C4596: 'Blablabla': illegal qualified name in member declaration",[11,1917,1918,1919,1924],{},"详细的原因可以查看MSDN关于[",[21,1920,1923],{"href":1921,"rel":1922},"https:\u002F\u002Fdocs.microsoft.com\u002Fen-us\u002Fcpp\u002Fbuild\u002Freference\u002Fpermissive-standards-conformance",[189],"permissive","]的文档，这个功能是为了让代码更加符合标准以提高代码的可移植性。",[11,1926,1927],{},"修正方式文档中已经有提供，通常都是类似这样的修改：",[44,1929,1932],{"className":1930,"code":1931,"language":49},[47],"template \u003Ctypename T_Ptr, typename Pred>\n\nclass RegistryWithPred : public AbstractRegistry\u003CT_Ptr, std::vector\u003CT_Ptr*>> {\n\npublic:\n- typedef typename RegistryWithPred\u003CT_Ptr, Pred>::iterator iterator;\n- typedef typename RegistryWithPred\u003CT_Ptr, Pred>::const_iterator const_iterator;\n+ typedef typename \u002F*RegistryWithPred\u003CT_Ptr, Pred>::*\u002Fiterator iterator;\n+ typedef typename \u002F*RegistryWithPred\u003CT_Ptr, Pred>::*\u002Fconst_iterator const_iterator;\n\nRegistryWithPred(void) {\n\n}\n",[51,1933,1931],{"__ignoreMap":53},{"title":53,"searchDepth":193,"depth":194,"links":1935},[1936,1937,1938],{"id":1845,"depth":193,"text":1846},{"id":1879,"depth":193,"text":1880},{"id":1906,"depth":193,"text":1907},"2017-06-24",{"layout":202,"status":203,"published":204,"author":1941,"author_login":207,"author_email":208,"wordpress_id":1942,"wordpress_url":1943,"date_gmt":1944,"excerpt":1945},{"display_name":206,"login":207,"email":208,"url":53},1796,"\u002F\u002F?p=1796","2017-06-24 11:58:07 +0000",{"type":8,"value":1946},[1947],[11,1948,1839],{},"\u002F2017-06-24-ue4-compile-errors-log",{"title":1834,"description":1839},"_legacy\u002F2017\u002F2017-06-24-ue4-compile-errors-log",[220,1953],"Error","N8GHUqThYgjHtwWVx0yo1qhwm9aqaEhhIWiClvRAHzo",85,1788763178265]