[{"data":1,"prerenderedAt":2195},["ShallowReactive",2],{"page-UE4-13":3,"page-count-UE4":1358},[4,309,444,531,2068],{"id":5,"title":6,"body":7,"date":285,"description":13,"extension":286,"meta":287,"navigation":290,"path":302,"seo":303,"stem":304,"tags":305,"__hash__":308},"blogs\u002F_legacy\u002F2015\u002F2015-08-16-ue4-event-dispatcher-and-delegate.md","事件调度器及C++中的使用",{"type":8,"value":9,"toc":278},"minimark",[10,14,17,20,24,27,30,33,40,43,48,51,55,58,61,64,67,70,73,163,166,202,205,240,243,251,254,260,263,268,271,274],[11,12,13],"p",{},"事件调度器非常的适合在各个蓝图之间实现通信功能。",[11,15,16],{},"当前UE4版本4.8.3。",[11,18,19],{},"在蓝图中，事件调度器的作用就像是事件的派发器。通过将事件预先的绑定在事件调度器上，可以让系统可以在需要时将事件派发给所有已经绑定的事件。",[21,22,23],"h2",{"id":23},"事件调度器的使用",[11,25,26],{},"一个比较常见的使用事件调度器的地方，就是关卡蓝图。",[11,28,29],{},"关卡蓝图中的很多物体的Actor及其逻辑，如果要脱离关卡蓝图的话会比较难于使用。因此，可以通过将关卡蓝图中实现好的功能绑定到某个类，例如GameMode的事件调度器上来方便调度。",[11,31,32],{},"如下图，在关卡蓝图的BeginPlay中将功能绑定到GameMode上：",[11,34,35],{},[36,37],"img",{"alt":38,"src":39},"image","\u002Fwp-content\u002Fuploads\u002F2015\u002F08\u002Fimage_thumb1.png",[11,41,42],{},"然后可以在GameMode的蓝图中，设定定时的调度关卡蓝图上的功能",[11,44,45],{},[36,46],{"alt":38,"src":47},"\u002Fwp-content\u002Fuploads\u002F2015\u002F08\u002Fimage_thumb2.png",[11,49,50],{},"事件调度器同时支持解绑和解绑全部，以方便对事件调度的逻辑进行进一步的控制。",[21,52,54],{"id":53},"delegate","Delegate",[11,56,57],{},"在C++和蓝图混合使用时，使用Blueprint Function Library可以方便的实现蓝图到C++的调用。如果要实现C++对蓝图的逻辑的话，事件调度机制就非常的方便。",[11,59,60],{},"在C++中，与事件调度器对应的是Delegate机制。事实上，Delegate机制的涵盖范围比事件调度器要大一些。",[11,62,63],{},"Delegate机制是一种常见的设计模式，相信做程序的童鞋都比较熟悉。这里不做多余的说明了。",[11,65,66],{},"UE4官方对Delegate的翻译名称唯代理。按照类型，分为单播代理和多播代理。其中，多播代理与事件调度器的功能类似，而单播代理更接近单纯的代理，也就是只能绑定一个执行函数。",[11,68,69],{},"要让多播代理像是事件调度器一样使用的话，需要将其定义为Dynamic。对于单播代理也是一样的。",[11,71,72],{},"在C++中使用UE4的代理功能，需要使用官方提供的宏进行定义。",[74,75,76,87],"table",{},[77,78,79],"thead",{},[80,81,82,85],"tr",{},[83,84],"th",{},[83,86],{},[88,89,90,99,107,115,123,131,139,147,155],"tbody",{},[80,91,92,96],{},[93,94,95],"td",{},"函数签名",[93,97,98],{},"声明宏",[80,100,101,104],{},[93,102,103],{},"void Function()",[93,105,106],{},"DECLARE_DELEGATE( DelegateName )",[80,108,109,112],{},[93,110,111],{},"void Function( Param1 )",[93,113,114],{},"DECLARE_DELEGATE_OneParam( DelegateName, Param1Type )",[80,116,117,120],{},[93,118,119],{},"void Function( Param1, Param2 )",[93,121,122],{},"DECLARE_DELEGATE_TwoParams( DelegateName, Param1Type, Param2Type )",[80,124,125,128],{},[93,126,127],{},"void Function( Param1, Param2, ... )",[93,129,130],{},"DECLARE_DELEGATE_NumParams( DelegateName, Param1Type, Param2Type, ... )",[80,132,133,136],{},[93,134,135],{},"RetVal Function()",[93,137,138],{},"DECLARE_DELEGATE_RetVal( RetValType, DelegateName )",[80,140,141,144],{},[93,142,143],{},"RetVal Function( Param1 )",[93,145,146],{},"DECLARE_DELEGATE_RetVal_OneParam( RetValType, DelegateName, Param1Type )",[80,148,149,152],{},[93,150,151],{},"RetVal Function( Param1, Param2 )",[93,153,154],{},"DECLARE_DELEGATE_RetVal_TwoParams( RetValType, DelegateName, Param1Type, Param2Type )",[80,156,157,160],{},[93,158,159],{},"RetVal Function( Param1, Param2, ... )",[93,161,162],{},"DECLARE_DELEGATE_RetVal_NumParams( RetValType, DelegateName, Param1Type, Param2Type, ... )",[11,164,165],{},"针对不同的代理类型，使用不同的宏前缀即可：",[74,167,168,176],{},[77,169,170],{},[80,171,172,174],{},[83,173],{},[83,175],{},[88,177,178,186,194],{},[80,179,180,183],{},[93,181,182],{},"多播代理",[93,184,185],{},"DECLARE_MULTICAST_DELEGATE...",[80,187,188,191],{},[93,189,190],{},"动态单播代理",[93,192,193],{},"DECLARE_DYNAMIC_DELEGATE...",[80,195,196,199],{},[93,197,198],{},"动态多播代理",[93,200,201],{},"DECLARE_DYNAMIC_MULTICAST_DELEGATE...",[11,203,204],{},"实际使用时，首先要对代理类型进行定义",[206,207,212],"pre",{"className":208,"code":209,"language":210,"meta":211,"style":211},"language-cpp shiki shiki-themes github-light-high-contrast github-dark monokai","DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FDspLRValDelegate, float, LVals, float, RVals);\n","cpp","",[213,214,215],"code",{"__ignoreMap":211},[216,217,220,224,228,232,235,237],"span",{"class":218,"line":219},"line",1,[216,221,223],{"class":222},"scAT4","DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams",[216,225,227],{"class":226},"s0idv","(FDspLRValDelegate, ",[216,229,231],{"class":230},"sGZGq","float",[216,233,234],{"class":226},", LVals, ",[216,236,231],{"class":230},[216,238,239],{"class":226},", RVals);\n",[11,241,242],{},"然后在具体的类，例如GameState中进行具体的声明",[206,244,249],{"className":245,"code":247,"language":248},[246],"language-text","UPROPERTY(BlueprintAssignable, Category = \"SoundFuncs\")\n    FDspLRValDelegate  DspLRVals;\n","text",[213,250,247],{"__ignoreMap":211},[11,252,253],{},"这样一来，就可以在需要调用这个代理的地方进行调用了，例如在某个数据生成的地方。",[206,255,258],{"className":256,"code":257,"language":248},[246],"AMyGameState* tags = Cast\u003CAMyGameState>(SL_Contex.LC_cGameState);\nif (tags)\n    tags->DspLRVals.Broadcast(tfLval, tfRval);\n",[213,259,257],{"__ignoreMap":211},[11,261,262],{},"之后，就可以在蓝图中向这个多播代理绑定事件来获得生成的数据了",[11,264,265],{},[36,266],{"alt":38,"src":267},"\u002Fwp-content\u002Fuploads\u002F2015\u002F08\u002Fimage_thumb3.png",[21,269,270],{"id":270},"总结",[11,272,273],{},"事件调度器的机制在逻辑实现中非常的方便，尤其是在关卡设计中，可能会比较经常用到。使用中也没有遇到什么特别需要注意的地方，逻辑很单纯。",[275,276,277],"style",{},"html pre.shiki code .scAT4, html code.shiki .scAT4{--shiki-default:#622CBC;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html pre.shiki code .s0idv, html code.shiki .s0idv{--shiki-default:#0E1116;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .sGZGq, html code.shiki .sGZGq{--shiki-default:#A0111F;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit;--shiki-sepia:#66D9EF;--shiki-sepia-font-style:italic}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":211,"searchDepth":279,"depth":280,"links":281},2,3,[282,283,284],{"id":23,"depth":279,"text":23},{"id":53,"depth":279,"text":54},{"id":270,"depth":279,"text":270},"2015-08-16","md",{"layout":288,"status":289,"published":290,"author":291,"author_login":293,"author_email":294,"wordpress_id":295,"wordpress_url":296,"date_gmt":297,"excerpt":298},"post","publish",true,{"display_name":292,"login":293,"email":294,"url":211},"风铃","flinkor","flinkor@foxmail.com",1450,"\u002F\u002F?p=1450","2015-08-16 04:00:50 +0000",{"type":8,"value":299},[300],[11,301,13],{},"\u002F2015-08-16-ue4-event-dispatcher-and-delegate",{"title":6,"description":13},"_legacy\u002F2015\u002F2015-08-16-ue4-event-dispatcher-and-delegate",[306,307,54],"UE4","事件调度器","erOr00Vt93ckLDdi2Mv8NeMJyYp0YYoVyMZW1VTURTs",{"id":310,"title":311,"body":312,"date":425,"description":316,"extension":286,"meta":426,"navigation":290,"path":438,"seo":439,"stem":440,"tags":441,"__hash__":443},"blogs\u002F_legacy\u002F2015\u002F2015-08-11-ue4-level-streaming.md","UE4流关卡",{"type":8,"value":313,"toc":419},[314,317,320,323,326,329,340,343,352,355,358,361,364,367,370,373,376,379,383,386,389,392,395,398,401,404,407,410,413,416],[11,315,316],{},"流关卡可以使得关卡内容只在玩家“需要”的时候才加载，在很多游戏中都有使用这个技术。",[11,318,319],{},"当前UE4版本4.11.0 P6。",[11,321,322],{},"官方提供的流关卡功能目前有两种应用方式。",[21,324,325],{"id":325},"世界构成器",[11,327,328],{},"有点类似于Tile地图制作的方法，可以将子关卡拼成大地图。方便关卡设计人员的并行开发以及内容的复用。",[11,330,331,332,339],{},"这部分官方有提供详细的",[333,334,338],"a",{"href":335,"rel":336},"https:\u002F\u002Fdocs.unrealengine.com\u002Flatest\u002FCHN\u002FEngine\u002FLevelStreaming\u002FWorldBrowser\u002Findex.html",[337],"nofollow","文档","可供参考。这里只作简短的记录。",[11,341,342],{},"开启世界构成器的部分，属性的路径稍微有些变更。",[11,344,345,346,351],{},"关于Simplygon，虽然官方说明上是说引擎自带的，但是要使用的话需要Simplygon官方的许可证。有许可证之后可以参照Simplygon官方的",[333,347,350],{"href":348,"rel":349},"https:\u002F\u002Fwww.simplygon.com\u002Fmedia\u002F1636\u002Fsimplygonue4integration.pdf",[337],"说明","在UE4中开启相关功能。",[21,353,354],{"id":354},"流关卡",[11,356,357],{},"如果关闭World Composition开关的话，就是“正常”的使用流关卡功能了。",[11,359,360],{},"使用流关卡功能时，相关界面会比世界构成器时有一些功能上的变更。",[11,362,363],{},"在此功能下用于计算每个关卡大小的Level Bounds不会再被创建。",[11,365,366],{},"在关卡列表中可以对每个子关卡的动态加载方式进行选择",[11,368,369],{},"关卡左边有蓝色图标的为使用蓝图进行动态加载的子关卡。",[11,371,372],{},"“总是加载”的子关卡在游戏开始后默认是可见的。",[11,374,375],{},"“蓝图”控制动态加载的子关卡还可以在关卡详细属性中进行单独的配置",[11,377,378],{},"关卡的载入以及可视性可以通过很多方法进行控制。",[21,380,382],{"id":381},"level-streaming-volume","Level Streaming Volume",[11,384,385],{},"当玩家进入体积中时，被绑定的子关卡就会进行相应的变更。默认的情况下，子关卡将会显示出来，而玩家离开时就会将关卡移除。",[11,387,388],{},"具体的功能对应，可以在属性中进行调整：",[11,390,391],{},"作用都比较直观。",[11,393,394],{},"子关卡和体积的绑定是在关卡详细设定中进行的。",[11,396,397],{},"Level Streaming Volume必须放到永久关卡中才会起作用。",[11,399,400],{},"对于简单的逻辑使用关卡流体积非常的方便。",[21,402,403],{"id":403},"蓝图",[11,405,406],{},"对于一些复制的逻辑，可以使用蓝图对关卡的载入进行控制。",[11,408,409],{},"例如，使用触发器对关卡的载入进行控制。",[11,411,412],{},"或者用按钮进行调试。",[11,414,415],{},"蓝图和Level Streaming Volume联合使用时可能会出现冲突，使用时需要注意。",[11,417,418],{},"关卡的载入和移除都是异步的，可以在操作完成之后再触发其他事件，例如打开通往该关卡的门。",{"title":211,"searchDepth":279,"depth":280,"links":420},[421,422,423,424],{"id":325,"depth":279,"text":325},{"id":354,"depth":279,"text":354},{"id":381,"depth":279,"text":382},{"id":403,"depth":279,"text":403},"2015-08-11",{"layout":288,"status":289,"published":290,"author":427,"author_login":428,"author_email":429,"author_url":430,"wordpress_id":431,"wordpress_url":432,"date_gmt":433,"excerpt":434},{"display_name":428,"login":428,"email":429,"url":430},"chaoshikari","chaoshikari@gmail.com","\u002F",1467,"\u002F\u002F?p=1467","2015-08-11 11:34:05 +0000",{"type":8,"value":435},[436],[11,437,316],{},"\u002F2015-08-11-ue4-level-streaming",{"title":311,"description":316},"_legacy\u002F2015\u002F2015-08-11-ue4-level-streaming",[306,442],"level-streaming","-i3VivbL-5U3ehcqzG7IacDir1BQ9_6sNI3XrjU5u2Q",{"id":445,"title":446,"body":447,"date":515,"description":451,"extension":286,"meta":516,"navigation":290,"path":525,"seo":526,"stem":527,"tags":528,"__hash__":530},"blogs\u002F_legacy\u002F2015\u002F2015-08-08-ue4-windows10-update-log.md","UE4的Windows10升级记录",{"type":8,"value":448,"toc":513},[449,452,455,458,461,464,479,482,485,494,507,510],[11,450,451],{},"一时冲动下把系统升级到windows10了，在这样的早期自然是遇到了很多问题。虽然Windows10早就发布了技术预览版，但是很多软件都因为技术上或是其他的什么问题而没有办法迅速的对操作系统的升级进行跟进。比如说支付宝到目前为止依然没有提供windows10的数字证书解决方案……",[11,453,454],{},"按照微软之前的宣传来看，win10似乎进一步加强了应用程序的权限控制。在默认运行的情况下，各个进程之间无法相互进行干涉。直接导致迅雷快鸟无法正常的进行加速，解决方案是把迅雷快鸟和迅雷都使用管理员权限运行。不过这种问题应该过一段时间就能解决了，一般“整合”的系统都会把这些功能给去掉。就像安装ghost版的win7的情况下基本不会遇到烦人的UAC一样。",[11,456,457],{},"不过这些都不是什么太重要的问题，升级了win10之后遇到的最大的麻烦来自UE4。",[11,459,460],{},"首先的一个问题是，UE4并不支持vs2015。赶时髦的安装了vs2015之后的结果是，最后又安装了一个vs2013……主要原因是在UE的编辑器中无法识别vs2015的c++编译器，导致无法对项目进行实时编译。",[11,462,463],{},"另有一个问题就是在使用vs打开项目时可能会遇到这样的报错：",[465,466,467,470,473,476],"blockquote",{},[11,468,469],{},"1>------ 已启动生成: 项目: Test_mp, 配置: Development_Editor x64 ------",[11,471,472],{},"1> 系统找不到指定的路径。",[11,474,475],{},"1>C:\\Program Files (x86)\\MSBuild\\Microsoft.Cpp\\v4.0\\V140\\Microsoft.MakeFile.Targets(37,5): error MSB3073: 命令“\"D:\\Software\\Epic Games\\4.8\\Engine\\Build\\BatchFiles\\Build.bat\" Test_mpEditor Win64 Development \"F:\\Unreal\\Test_mp\\Test_mp.uproject\" -rocket”已退出，代码为 3。",[11,477,478],{},"========== 生成: 成功 0 个，失败 1 个，最新 0 个，跳过 0 个 ==========",[11,480,481],{},"这个错误之前也遇到过，其原因是ue4的安装目录改变了，导致编译时无法找到Build.bat。解决方案也很简单，只要打开UE4编辑器，在“文件”菜单下找到“刷新visual studio项目”即可。不过，如果之前关闭的时候是编译失败的话，这个时候是无法打开UE4编辑器的。要手动去修改项目的路径配置将会是一个很浩大的工程。不过，其实只要安装UE4的时候使用同样的路径就可以了……只不过重装系统的话，多少都会有些重新整理的冲动。另外的，在进行引擎版本升级的时候也会有类似的问题。故而在进行大版本迁移的时候最好保留一段时间的旧版本引擎。",[11,483,484],{},"当前UE4的正式版本为4.8.3。而4.9的预览版已经更新到P2了。",[11,486,487,488,493],{},"关于win10和vs2015，官方在",[333,489,492],{"href":490,"rel":491},"https:\u002F\u002Fforums.unrealengine.com\u002Fshowthread.php?78220-Unreal-Engine-4-9-Preview&p=342676#post342676",[337],"4.9预览版的更新说明","里是这样解释的：",[495,496,497,501,504],"ul",{},[498,499,500],"li",{},"UE4.9预览版还不支持vs2015，当前Github上的vs2015支持功能处于试验状态，预计4.9.0版本释出",[498,502,503],{},"UE4.9可以运行在win10上，但是还没有彻底的检验过",[498,505,506],{},"DX12在UE4.9中处于试验状态，但是在Win10上可以通过 -D3D12参数开启",[11,508,509],{},"到目前为止，UE4.8.3在Win10上运行一切正常，没有遇到什么太大的问题。",[11,511,512],{},"Win10总体试用感觉还是不错的，如果短期内没有什么重大的问题的话，大概就会一直使用了~",{"title":211,"searchDepth":279,"depth":280,"links":514},[],"2015-08-08",{"layout":288,"status":289,"published":290,"author":517,"author_login":293,"author_email":294,"wordpress_id":518,"wordpress_url":519,"date_gmt":520,"excerpt":521},{"display_name":292,"login":293,"email":294,"url":211},1415,"\u002F\u002F?p=1415","2015-08-08 04:47:37 +0000",{"type":8,"value":522},[523],[11,524,451],{},"\u002F2015-08-08-ue4-windows10-update-log",{"title":446,"description":451},"_legacy\u002F2015\u002F2015-08-08-ue4-windows10-update-log",[306,529],"win10","AzHDZItPQVH87tBRAzmOWlOc6ZC7YaJ3-ysmH1Km2is",{"id":532,"title":533,"body":534,"date":2052,"description":538,"extension":286,"meta":2053,"navigation":290,"path":2062,"seo":2063,"stem":2064,"tags":2065,"__hash__":2067},"blogs\u002F_legacy\u002F2015\u002F2015-08-01-ue4-package-logs-android.md","UE4游戏Package记录（Android）",{"type":8,"value":535,"toc":2046},[536,539,542,545,554,557,565,573,576,579,582,585,588,591,594,597,600,603,1960,1963,1969,1972,1975,1978,1984,1987,1993,1996,1999,2010,2013,2016,2019,2022,2030,2037,2040,2043],[11,537,538],{},"Android的打包比Windows下要稍微麻烦一些，因为使用的编译器不同导致的问题也就多了起来。",[11,540,541],{},"当前使用的UE4版本为4.10.1。",[21,543,544],{"id":544},"基本步骤",[11,546,547,548,553],{},"UE4打包Android的教程官方是有提供的，可以看",[333,549,552],{"href":550,"rel":551},"https:\u002F\u002Fdocs.unrealengine.com\u002Flatest\u002FINT\u002FPlatforms\u002FAndroid\u002FGettingStarted\u002F",[337],"这里","。",[11,555,556],{},"下面只是简单的做一下总结的感觉，首先需要进行的是相关环境的安装。android sdk、ndk以及很多其他的东西，直接使用引擎自带的安装器就可以一次性搞定了。安装器在引擎如下的目录中可以找到",[465,558,559],{},[11,560,561,564],{},[216,562,563],{},"ENGINE INSTALL LOCATION","\\Engine\\Extras\\Android\\CodeWorksforAndroid-1R6u1-windows.exe",[11,566,567,568,572],{},"开发必备环境的设定可以看[",[333,569,552],{"href":570,"rel":571},"https:\u002F\u002Fdocs.unrealengine.com\u002Fen-us\u002FPlatforms\u002FAndroid\u002FReference",[337],"]。",[11,574,575],{},"根据网络情况的不同，安装时间可能会比较长。",[11,577,578],{},"安装好之后其实就可以进行Android打包了，如果之前进行过Windows打包的话，基本不需要额外的设置。",[21,580,581],{"id":581},"插件问题",[11,583,584],{},"Android打包过程中很容易遇到的问题是插件上的，例如，如果在项目中有使用FMod的话，就需要进行一些额外的工作。",[11,586,587],{},"首先我们需要的是排查工具，在Android的SDK中有提供可以用于错误排查的工具。路径位于sdk的tools目录中，使用monitor.bat即可。",[11,589,590],{},"为了使用方便，在LogCat中添加新的过滤器就可以方便的对UE4的输出记录进行排查了。",[11,592,593],{},"如果在项目中有使用FMod的话，游戏在Android上是无法直接打开的，查看输出记录可以看到。",[11,595,596],{},"FMod的库文件没有被正确的找到，其实这是由于没有正确的按照FMod官方的配置说明进行配置导致的。在FMod的文档中其实是有说明的，不过没有到打包这一步的时候也并不需要进行配置。",[11,598,599],{},"当前FMod的Android打包需要对UE4的打包设置进行修改才行，首先，我们需要去GitHub上下载源码版的引擎。",[11,601,602],{},"并对UEDeployAndroid.cs进行修改，在CopyPluginLibs函数的末尾，添加如下的代码：",[206,604,608],{"className":605,"code":606,"language":607,"meta":211,"style":211},"language-java shiki shiki-themes github-light-high-contrast github-dark monokai","Console.WriteLine(\"Plugin Deployment\");\n\nList\u003Cstring> PluginLibraryReferences = new List\u003Cstring>();\n\nforeach (PluginInfo Plugin in Plugins.ReadAvailablePlugins(UnrealBuildTool.GetUProjectFile()))\n\n{\n\n    string AndroidDirectory = Path.Combine(Plugin.Directory, \"Binaries\u002FAndroid\");\n\n    string DeployFile = Path.Combine(AndroidDirectory, \"deploy.txt\");\n\n    if (File.Exists(DeployFile))\n\n    {\n\n        Console.WriteLine(\"Using Plugin Deployment file '{0}'\", DeployFile);\n\n        string DestLibraryDirectory = Path.Combine(UE4BuildPath, \"libs\u002Farmeabi-v7a\");\n\n        string DestJarDirectory = Path.Combine(UE4BuildPath, \"libs\");\n\n        foreach (string Name in File.ReadAllLines(DeployFile))\n\n        {\n\n            Console.WriteLine(\"Have file entry '{0}'\", Name);\n\n            string PluginFileExt = Path.GetExtension(Name);\n\n            if (PluginFileExt == \".so\")\n\n            {\n\n                string SourceFile = Path.Combine(AndroidDirectory, Name);\n\n                string DestFile = Path.Combine(DestLibraryDirectory, Name);\n\n                Console.WriteLine(\"Copying plugin .so file '{0}' to '{1}'\", SourceFile, DestFile);\n\n                if (File.Exists(DestFile))\n\n                {\n\n                    File.Delete(DestFile);\n\n                }\n\n                File.Copy(SourceFile, DestFile);\n\n                \u002F\u002F Also remember it for GameActivity\n\n                PluginLibraryReferences.Add(Name);\n\n            }\n\n            else if (PluginFileExt == \".jar\")\n\n            {\n\n                string SourceFile = Path.Combine(AndroidDirectory, Name);\n\n                string DestFile = Path.Combine(DestJarDirectory, Name);\n\n                Console.WriteLine(\"Copying plugin .jar file '{0}' to '{1}'\", SourceFile, DestFile);\n\n                if (File.Exists(DestFile))\n\n                {\n\n                    File.Delete(DestFile);\n\n                }\n\n                File.Copy(SourceFile, DestFile);\n\n            }\n\n        }\n\n    }\n\n}\n\n\u002F\u002F Enter all .so references into GameActivity java file\n\nif (PluginLibraryReferences.Count != 0)\n\n{\n\n    Console.WriteLine(\"Adding Plugin Deployment library references\");\n\n    String GameActivityFileName = Path.Combine(UE4BuildPath, \"src\u002Fcom\u002Fepicgames\u002Fue4\u002FGameActivity.java\");\n\n    List\u003Cstring> ActivityContents = new List\u003Cstring>(File.ReadAllLines(GameActivityFileName));\n\n    int LoadLibraryIndex = -1;\n\n    for (int i = 1; i \u003C ActivityContents.Count; ++i)\n\n    {\n\n        if (ActivityContents\u003Ci>.Contains(\"System.loadLibrary\"))\n\n        {\n\n            LoadLibraryIndex = i;\n\n            break;\n\n        }\n\n    }\n\n    if (LoadLibraryIndex != -1)\n\n    {\n\n        \u002F\u002F Insert in reverse order\n\n        PluginLibraryReferences.Reverse();\n\n        foreach (string Reference in PluginLibraryReferences)\n\n        {\n\n            Console.WriteLine(\"Adding library reference {0} at line {1}\", Reference, LoadLibraryIndex);\n\n            string ShortName = Path.GetFileNameWithoutExtension(Reference);\n\n            if (ShortName.StartsWith(\"lib\")) \u002F\u002F Without the lib prefix\n\n            {\n\n                ShortName = ShortName.Substring(3);\n\n            }\n\n            ActivityContents.Insert(LoadLibraryIndex, String.Format(\"\\t\\tSystem.loadLibrary(\\\"{0}\\\");\", ShortName));\n\n        }\n\n    }\n\n    File.WriteAllLines(GameActivityFileName, ActivityContents.ToArray());\n\n}\n\n\u002F\u002F PLUGIN DEPLOYMENT END\n","java",[213,609,610,628,633,669,674,704,709,715,720,743,748,768,773,788,793,799,804,820,825,845,850,869,874,894,899,905,910,926,931,947,952,970,975,981,986,1001,1006,1021,1026,1042,1047,1060,1065,1071,1076,1088,1093,1099,1104,1116,1121,1128,1133,1144,1149,1155,1160,1178,1183,1188,1193,1206,1211,1225,1230,1244,1249,1260,1265,1270,1275,1284,1289,1294,1299,1308,1313,1318,1323,1329,1334,1340,1345,1351,1356,1362,1367,1385,1390,1395,1400,1415,1420,1442,1447,1480,1485,1505,1510,1543,1548,1553,1558,1590,1595,1600,1605,1616,1621,1629,1634,1639,1644,1649,1654,1670,1675,1680,1685,1691,1696,1708,1713,1726,1731,1736,1741,1756,1761,1777,1782,1804,1809,1814,1819,1840,1845,1850,1855,1896,1901,1906,1911,1916,1921,1939,1944,1949,1954],{"__ignoreMap":211},[216,611,612,615,618,621,625],{"class":218,"line":219},[216,613,614],{"class":226},"Console.",[216,616,617],{"class":222},"WriteLine",[216,619,620],{"class":226},"(",[216,622,624],{"class":623},"sZnmU","\"Plugin Deployment\"",[216,626,627],{"class":226},");\n",[216,629,630],{"class":218,"line":279},[216,631,632],{"emptyLinePlaceholder":290},"\n",[216,634,635,639,643,646,649,652,656,659,662,664,666],{"class":218,"line":280},[216,636,638],{"class":637},"ss1GH","List",[216,640,642],{"class":641},"suI3T","\u003C",[216,644,645],{"class":230},"string",[216,647,648],{"class":641},"> ",[216,650,651],{"class":226},"PluginLibraryReferences",[216,653,655],{"class":654},"sLXdl"," =",[216,657,658],{"class":654}," new",[216,660,661],{"class":637}," List",[216,663,642],{"class":226},[216,665,645],{"class":230},[216,667,668],{"class":226},">();\n",[216,670,672],{"class":218,"line":671},4,[216,673,632],{"emptyLinePlaceholder":290},[216,675,677,680,683,686,689,692,695,698,701],{"class":218,"line":676},5,[216,678,679],{"class":222},"foreach",[216,681,682],{"class":226}," (",[216,684,685],{"class":637},"PluginInfo",[216,687,688],{"class":637}," Plugin",[216,690,691],{"class":226}," in Plugins.",[216,693,694],{"class":222},"ReadAvailablePlugins",[216,696,697],{"class":226},"(UnrealBuildTool.",[216,699,700],{"class":222},"GetUProjectFile",[216,702,703],{"class":226},"()))\n",[216,705,707],{"class":218,"line":706},6,[216,708,632],{"emptyLinePlaceholder":290},[216,710,712],{"class":218,"line":711},7,[216,713,714],{"class":226},"{\n",[216,716,718],{"class":218,"line":717},8,[216,719,632],{"emptyLinePlaceholder":290},[216,721,723,726,729,732,735,738,741],{"class":218,"line":722},9,[216,724,725],{"class":226},"    string AndroidDirectory ",[216,727,728],{"class":654},"=",[216,730,731],{"class":226}," Path.",[216,733,734],{"class":222},"Combine",[216,736,737],{"class":226},"(Plugin.Directory, ",[216,739,740],{"class":623},"\"Binaries\u002FAndroid\"",[216,742,627],{"class":226},[216,744,746],{"class":218,"line":745},10,[216,747,632],{"emptyLinePlaceholder":290},[216,749,751,754,756,758,760,763,766],{"class":218,"line":750},11,[216,752,753],{"class":226},"    string DeployFile ",[216,755,728],{"class":654},[216,757,731],{"class":226},[216,759,734],{"class":222},[216,761,762],{"class":226},"(AndroidDirectory, ",[216,764,765],{"class":623},"\"deploy.txt\"",[216,767,627],{"class":226},[216,769,771],{"class":218,"line":770},12,[216,772,632],{"emptyLinePlaceholder":290},[216,774,776,779,782,785],{"class":218,"line":775},13,[216,777,778],{"class":654},"    if",[216,780,781],{"class":226}," (File.",[216,783,784],{"class":222},"Exists",[216,786,787],{"class":226},"(DeployFile))\n",[216,789,791],{"class":218,"line":790},14,[216,792,632],{"emptyLinePlaceholder":290},[216,794,796],{"class":218,"line":795},15,[216,797,798],{"class":226},"    {\n",[216,800,802],{"class":218,"line":801},16,[216,803,632],{"emptyLinePlaceholder":290},[216,805,807,810,812,814,817],{"class":218,"line":806},17,[216,808,809],{"class":226},"        Console.",[216,811,617],{"class":222},[216,813,620],{"class":226},[216,815,816],{"class":623},"\"Using Plugin Deployment file '{0}'\"",[216,818,819],{"class":226},", DeployFile);\n",[216,821,823],{"class":218,"line":822},18,[216,824,632],{"emptyLinePlaceholder":290},[216,826,828,831,833,835,837,840,843],{"class":218,"line":827},19,[216,829,830],{"class":226},"        string DestLibraryDirectory ",[216,832,728],{"class":654},[216,834,731],{"class":226},[216,836,734],{"class":222},[216,838,839],{"class":226},"(UE4BuildPath, ",[216,841,842],{"class":623},"\"libs\u002Farmeabi-v7a\"",[216,844,627],{"class":226},[216,846,848],{"class":218,"line":847},20,[216,849,632],{"emptyLinePlaceholder":290},[216,851,853,856,858,860,862,864,867],{"class":218,"line":852},21,[216,854,855],{"class":226},"        string DestJarDirectory ",[216,857,728],{"class":654},[216,859,731],{"class":226},[216,861,734],{"class":222},[216,863,839],{"class":226},[216,865,866],{"class":623},"\"libs\"",[216,868,627],{"class":226},[216,870,872],{"class":218,"line":871},22,[216,873,632],{"emptyLinePlaceholder":290},[216,875,877,880,883,886,889,892],{"class":218,"line":876},23,[216,878,879],{"class":222},"        foreach",[216,881,882],{"class":226}," (string ",[216,884,885],{"class":637},"Name",[216,887,888],{"class":226}," in File.",[216,890,891],{"class":222},"ReadAllLines",[216,893,787],{"class":226},[216,895,897],{"class":218,"line":896},24,[216,898,632],{"emptyLinePlaceholder":290},[216,900,902],{"class":218,"line":901},25,[216,903,904],{"class":226},"        {\n",[216,906,908],{"class":218,"line":907},26,[216,909,632],{"emptyLinePlaceholder":290},[216,911,913,916,918,920,923],{"class":218,"line":912},27,[216,914,915],{"class":226},"            Console.",[216,917,617],{"class":222},[216,919,620],{"class":226},[216,921,922],{"class":623},"\"Have file entry '{0}'\"",[216,924,925],{"class":226},", Name);\n",[216,927,929],{"class":218,"line":928},28,[216,930,632],{"emptyLinePlaceholder":290},[216,932,934,937,939,941,944],{"class":218,"line":933},29,[216,935,936],{"class":226},"            string PluginFileExt ",[216,938,728],{"class":654},[216,940,731],{"class":226},[216,942,943],{"class":222},"GetExtension",[216,945,946],{"class":226},"(Name);\n",[216,948,950],{"class":218,"line":949},30,[216,951,632],{"emptyLinePlaceholder":290},[216,953,955,958,961,964,967],{"class":218,"line":954},31,[216,956,957],{"class":654},"            if",[216,959,960],{"class":226}," (PluginFileExt ",[216,962,963],{"class":654},"==",[216,965,966],{"class":623}," \".so\"",[216,968,969],{"class":226},")\n",[216,971,973],{"class":218,"line":972},32,[216,974,632],{"emptyLinePlaceholder":290},[216,976,978],{"class":218,"line":977},33,[216,979,980],{"class":226},"            {\n",[216,982,984],{"class":218,"line":983},34,[216,985,632],{"emptyLinePlaceholder":290},[216,987,989,992,994,996,998],{"class":218,"line":988},35,[216,990,991],{"class":226},"                string SourceFile ",[216,993,728],{"class":654},[216,995,731],{"class":226},[216,997,734],{"class":222},[216,999,1000],{"class":226},"(AndroidDirectory, Name);\n",[216,1002,1004],{"class":218,"line":1003},36,[216,1005,632],{"emptyLinePlaceholder":290},[216,1007,1009,1012,1014,1016,1018],{"class":218,"line":1008},37,[216,1010,1011],{"class":226},"                string DestFile ",[216,1013,728],{"class":654},[216,1015,731],{"class":226},[216,1017,734],{"class":222},[216,1019,1020],{"class":226},"(DestLibraryDirectory, Name);\n",[216,1022,1024],{"class":218,"line":1023},38,[216,1025,632],{"emptyLinePlaceholder":290},[216,1027,1029,1032,1034,1036,1039],{"class":218,"line":1028},39,[216,1030,1031],{"class":226},"                Console.",[216,1033,617],{"class":222},[216,1035,620],{"class":226},[216,1037,1038],{"class":623},"\"Copying plugin .so file '{0}' to '{1}'\"",[216,1040,1041],{"class":226},", SourceFile, DestFile);\n",[216,1043,1045],{"class":218,"line":1044},40,[216,1046,632],{"emptyLinePlaceholder":290},[216,1048,1050,1053,1055,1057],{"class":218,"line":1049},41,[216,1051,1052],{"class":654},"                if",[216,1054,781],{"class":226},[216,1056,784],{"class":222},[216,1058,1059],{"class":226},"(DestFile))\n",[216,1061,1063],{"class":218,"line":1062},42,[216,1064,632],{"emptyLinePlaceholder":290},[216,1066,1068],{"class":218,"line":1067},43,[216,1069,1070],{"class":226},"                {\n",[216,1072,1074],{"class":218,"line":1073},44,[216,1075,632],{"emptyLinePlaceholder":290},[216,1077,1079,1082,1085],{"class":218,"line":1078},45,[216,1080,1081],{"class":226},"                    File.",[216,1083,1084],{"class":222},"Delete",[216,1086,1087],{"class":226},"(DestFile);\n",[216,1089,1091],{"class":218,"line":1090},46,[216,1092,632],{"emptyLinePlaceholder":290},[216,1094,1096],{"class":218,"line":1095},47,[216,1097,1098],{"class":226},"                }\n",[216,1100,1102],{"class":218,"line":1101},48,[216,1103,632],{"emptyLinePlaceholder":290},[216,1105,1107,1110,1113],{"class":218,"line":1106},49,[216,1108,1109],{"class":226},"                File.",[216,1111,1112],{"class":222},"Copy",[216,1114,1115],{"class":226},"(SourceFile, DestFile);\n",[216,1117,1119],{"class":218,"line":1118},50,[216,1120,632],{"emptyLinePlaceholder":290},[216,1122,1124],{"class":218,"line":1123},51,[216,1125,1127],{"class":1126},"sZdD5","                \u002F\u002F Also remember it for GameActivity\n",[216,1129,1131],{"class":218,"line":1130},52,[216,1132,632],{"emptyLinePlaceholder":290},[216,1134,1136,1139,1142],{"class":218,"line":1135},53,[216,1137,1138],{"class":226},"                PluginLibraryReferences.",[216,1140,1141],{"class":222},"Add",[216,1143,946],{"class":226},[216,1145,1147],{"class":218,"line":1146},54,[216,1148,632],{"emptyLinePlaceholder":290},[216,1150,1152],{"class":218,"line":1151},55,[216,1153,1154],{"class":226},"            }\n",[216,1156,1158],{"class":218,"line":1157},56,[216,1159,632],{"emptyLinePlaceholder":290},[216,1161,1163,1166,1169,1171,1173,1176],{"class":218,"line":1162},57,[216,1164,1165],{"class":654},"            else",[216,1167,1168],{"class":654}," if",[216,1170,960],{"class":226},[216,1172,963],{"class":654},[216,1174,1175],{"class":623}," \".jar\"",[216,1177,969],{"class":226},[216,1179,1181],{"class":218,"line":1180},58,[216,1182,632],{"emptyLinePlaceholder":290},[216,1184,1186],{"class":218,"line":1185},59,[216,1187,980],{"class":226},[216,1189,1191],{"class":218,"line":1190},60,[216,1192,632],{"emptyLinePlaceholder":290},[216,1194,1196,1198,1200,1202,1204],{"class":218,"line":1195},61,[216,1197,991],{"class":226},[216,1199,728],{"class":654},[216,1201,731],{"class":226},[216,1203,734],{"class":222},[216,1205,1000],{"class":226},[216,1207,1209],{"class":218,"line":1208},62,[216,1210,632],{"emptyLinePlaceholder":290},[216,1212,1214,1216,1218,1220,1222],{"class":218,"line":1213},63,[216,1215,1011],{"class":226},[216,1217,728],{"class":654},[216,1219,731],{"class":226},[216,1221,734],{"class":222},[216,1223,1224],{"class":226},"(DestJarDirectory, Name);\n",[216,1226,1228],{"class":218,"line":1227},64,[216,1229,632],{"emptyLinePlaceholder":290},[216,1231,1233,1235,1237,1239,1242],{"class":218,"line":1232},65,[216,1234,1031],{"class":226},[216,1236,617],{"class":222},[216,1238,620],{"class":226},[216,1240,1241],{"class":623},"\"Copying plugin .jar file '{0}' to '{1}'\"",[216,1243,1041],{"class":226},[216,1245,1247],{"class":218,"line":1246},66,[216,1248,632],{"emptyLinePlaceholder":290},[216,1250,1252,1254,1256,1258],{"class":218,"line":1251},67,[216,1253,1052],{"class":654},[216,1255,781],{"class":226},[216,1257,784],{"class":222},[216,1259,1059],{"class":226},[216,1261,1263],{"class":218,"line":1262},68,[216,1264,632],{"emptyLinePlaceholder":290},[216,1266,1268],{"class":218,"line":1267},69,[216,1269,1070],{"class":226},[216,1271,1273],{"class":218,"line":1272},70,[216,1274,632],{"emptyLinePlaceholder":290},[216,1276,1278,1280,1282],{"class":218,"line":1277},71,[216,1279,1081],{"class":226},[216,1281,1084],{"class":222},[216,1283,1087],{"class":226},[216,1285,1287],{"class":218,"line":1286},72,[216,1288,632],{"emptyLinePlaceholder":290},[216,1290,1292],{"class":218,"line":1291},73,[216,1293,1098],{"class":226},[216,1295,1297],{"class":218,"line":1296},74,[216,1298,632],{"emptyLinePlaceholder":290},[216,1300,1302,1304,1306],{"class":218,"line":1301},75,[216,1303,1109],{"class":226},[216,1305,1112],{"class":222},[216,1307,1115],{"class":226},[216,1309,1311],{"class":218,"line":1310},76,[216,1312,632],{"emptyLinePlaceholder":290},[216,1314,1316],{"class":218,"line":1315},77,[216,1317,1154],{"class":226},[216,1319,1321],{"class":218,"line":1320},78,[216,1322,632],{"emptyLinePlaceholder":290},[216,1324,1326],{"class":218,"line":1325},79,[216,1327,1328],{"class":226},"        }\n",[216,1330,1332],{"class":218,"line":1331},80,[216,1333,632],{"emptyLinePlaceholder":290},[216,1335,1337],{"class":218,"line":1336},81,[216,1338,1339],{"class":226},"    }\n",[216,1341,1343],{"class":218,"line":1342},82,[216,1344,632],{"emptyLinePlaceholder":290},[216,1346,1348],{"class":218,"line":1347},83,[216,1349,1350],{"class":226},"}\n",[216,1352,1354],{"class":218,"line":1353},84,[216,1355,632],{"emptyLinePlaceholder":290},[216,1357,1359],{"class":218,"line":1358},85,[216,1360,1361],{"class":1126},"\u002F\u002F Enter all .so references into GameActivity java file\n",[216,1363,1365],{"class":218,"line":1364},86,[216,1366,632],{"emptyLinePlaceholder":290},[216,1368,1370,1373,1376,1379,1383],{"class":218,"line":1369},87,[216,1371,1372],{"class":654},"if",[216,1374,1375],{"class":226}," (PluginLibraryReferences.Count ",[216,1377,1378],{"class":654},"!=",[216,1380,1382],{"class":1381},"stP0Q"," 0",[216,1384,969],{"class":226},[216,1386,1388],{"class":218,"line":1387},88,[216,1389,632],{"emptyLinePlaceholder":290},[216,1391,1393],{"class":218,"line":1392},89,[216,1394,714],{"class":226},[216,1396,1398],{"class":218,"line":1397},90,[216,1399,632],{"emptyLinePlaceholder":290},[216,1401,1403,1406,1408,1410,1413],{"class":218,"line":1402},91,[216,1404,1405],{"class":226},"    Console.",[216,1407,617],{"class":222},[216,1409,620],{"class":226},[216,1411,1412],{"class":623},"\"Adding Plugin Deployment library references\"",[216,1414,627],{"class":226},[216,1416,1418],{"class":218,"line":1417},92,[216,1419,632],{"emptyLinePlaceholder":290},[216,1421,1423,1426,1429,1431,1433,1435,1437,1440],{"class":218,"line":1422},93,[216,1424,1425],{"class":637},"    String",[216,1427,1428],{"class":226}," GameActivityFileName",[216,1430,655],{"class":654},[216,1432,731],{"class":226},[216,1434,734],{"class":222},[216,1436,839],{"class":226},[216,1438,1439],{"class":623},"\"src\u002Fcom\u002Fepicgames\u002Fue4\u002FGameActivity.java\"",[216,1441,627],{"class":226},[216,1443,1445],{"class":218,"line":1444},94,[216,1446,632],{"emptyLinePlaceholder":290},[216,1448,1450,1453,1455,1457,1459,1462,1464,1466,1468,1470,1472,1475,1477],{"class":218,"line":1449},95,[216,1451,1452],{"class":637},"    List",[216,1454,642],{"class":641},[216,1456,645],{"class":230},[216,1458,648],{"class":641},[216,1460,1461],{"class":226},"ActivityContents",[216,1463,655],{"class":654},[216,1465,658],{"class":654},[216,1467,661],{"class":637},[216,1469,642],{"class":226},[216,1471,645],{"class":230},[216,1473,1474],{"class":226},">(File.",[216,1476,891],{"class":222},[216,1478,1479],{"class":226},"(GameActivityFileName));\n",[216,1481,1483],{"class":218,"line":1482},96,[216,1484,632],{"emptyLinePlaceholder":290},[216,1486,1488,1491,1494,1496,1499,1502],{"class":218,"line":1487},97,[216,1489,1490],{"class":230},"    int",[216,1492,1493],{"class":226}," LoadLibraryIndex",[216,1495,655],{"class":654},[216,1497,1498],{"class":654}," -",[216,1500,1501],{"class":1381},"1",[216,1503,1504],{"class":226},";\n",[216,1506,1508],{"class":218,"line":1507},98,[216,1509,632],{"emptyLinePlaceholder":290},[216,1511,1513,1516,1518,1521,1524,1526,1529,1532,1534,1537,1540],{"class":218,"line":1512},99,[216,1514,1515],{"class":654},"    for",[216,1517,682],{"class":226},[216,1519,1520],{"class":230},"int",[216,1522,1523],{"class":226}," i",[216,1525,655],{"class":654},[216,1527,1528],{"class":1381}," 1",[216,1530,1531],{"class":226},"; i ",[216,1533,642],{"class":654},[216,1535,1536],{"class":226}," ActivityContents.Count; ",[216,1538,1539],{"class":654},"++",[216,1541,1542],{"class":226},"i)\n",[216,1544,1546],{"class":218,"line":1545},100,[216,1547,632],{"emptyLinePlaceholder":290},[216,1549,1551],{"class":218,"line":1550},101,[216,1552,798],{"class":226},[216,1554,1556],{"class":218,"line":1555},102,[216,1557,632],{"emptyLinePlaceholder":290},[216,1559,1561,1564,1566,1568,1570,1573,1576,1579,1582,1584,1587],{"class":218,"line":1560},103,[216,1562,1563],{"class":654},"        if",[216,1565,682],{"class":226},[216,1567,1461],{"class":637},[216,1569,642],{"class":654},[216,1571,1572],{"class":226},"i",[216,1574,1575],{"class":654},">",[216,1577,1578],{"class":226},".",[216,1580,1581],{"class":222},"Contains",[216,1583,620],{"class":226},[216,1585,1586],{"class":623},"\"System.loadLibrary\"",[216,1588,1589],{"class":226},"))\n",[216,1591,1593],{"class":218,"line":1592},104,[216,1594,632],{"emptyLinePlaceholder":290},[216,1596,1598],{"class":218,"line":1597},105,[216,1599,904],{"class":226},[216,1601,1603],{"class":218,"line":1602},106,[216,1604,632],{"emptyLinePlaceholder":290},[216,1606,1608,1611,1613],{"class":218,"line":1607},107,[216,1609,1610],{"class":226},"            LoadLibraryIndex ",[216,1612,728],{"class":654},[216,1614,1615],{"class":226}," i;\n",[216,1617,1619],{"class":218,"line":1618},108,[216,1620,632],{"emptyLinePlaceholder":290},[216,1622,1624,1627],{"class":218,"line":1623},109,[216,1625,1626],{"class":654},"            break",[216,1628,1504],{"class":226},[216,1630,1632],{"class":218,"line":1631},110,[216,1633,632],{"emptyLinePlaceholder":290},[216,1635,1637],{"class":218,"line":1636},111,[216,1638,1328],{"class":226},[216,1640,1642],{"class":218,"line":1641},112,[216,1643,632],{"emptyLinePlaceholder":290},[216,1645,1647],{"class":218,"line":1646},113,[216,1648,1339],{"class":226},[216,1650,1652],{"class":218,"line":1651},114,[216,1653,632],{"emptyLinePlaceholder":290},[216,1655,1657,1659,1662,1664,1666,1668],{"class":218,"line":1656},115,[216,1658,778],{"class":654},[216,1660,1661],{"class":226}," (LoadLibraryIndex ",[216,1663,1378],{"class":654},[216,1665,1498],{"class":654},[216,1667,1501],{"class":1381},[216,1669,969],{"class":226},[216,1671,1673],{"class":218,"line":1672},116,[216,1674,632],{"emptyLinePlaceholder":290},[216,1676,1678],{"class":218,"line":1677},117,[216,1679,798],{"class":226},[216,1681,1683],{"class":218,"line":1682},118,[216,1684,632],{"emptyLinePlaceholder":290},[216,1686,1688],{"class":218,"line":1687},119,[216,1689,1690],{"class":1126},"        \u002F\u002F Insert in reverse order\n",[216,1692,1694],{"class":218,"line":1693},120,[216,1695,632],{"emptyLinePlaceholder":290},[216,1697,1699,1702,1705],{"class":218,"line":1698},121,[216,1700,1701],{"class":226},"        PluginLibraryReferences.",[216,1703,1704],{"class":222},"Reverse",[216,1706,1707],{"class":226},"();\n",[216,1709,1711],{"class":218,"line":1710},122,[216,1712,632],{"emptyLinePlaceholder":290},[216,1714,1716,1718,1720,1723],{"class":218,"line":1715},123,[216,1717,879],{"class":222},[216,1719,882],{"class":226},[216,1721,1722],{"class":637},"Reference",[216,1724,1725],{"class":226}," in PluginLibraryReferences)\n",[216,1727,1729],{"class":218,"line":1728},124,[216,1730,632],{"emptyLinePlaceholder":290},[216,1732,1734],{"class":218,"line":1733},125,[216,1735,904],{"class":226},[216,1737,1739],{"class":218,"line":1738},126,[216,1740,632],{"emptyLinePlaceholder":290},[216,1742,1744,1746,1748,1750,1753],{"class":218,"line":1743},127,[216,1745,915],{"class":226},[216,1747,617],{"class":222},[216,1749,620],{"class":226},[216,1751,1752],{"class":623},"\"Adding library reference {0} at line {1}\"",[216,1754,1755],{"class":226},", Reference, LoadLibraryIndex);\n",[216,1757,1759],{"class":218,"line":1758},128,[216,1760,632],{"emptyLinePlaceholder":290},[216,1762,1764,1767,1769,1771,1774],{"class":218,"line":1763},129,[216,1765,1766],{"class":226},"            string ShortName ",[216,1768,728],{"class":654},[216,1770,731],{"class":226},[216,1772,1773],{"class":222},"GetFileNameWithoutExtension",[216,1775,1776],{"class":226},"(Reference);\n",[216,1778,1780],{"class":218,"line":1779},130,[216,1781,632],{"emptyLinePlaceholder":290},[216,1783,1785,1787,1790,1793,1795,1798,1801],{"class":218,"line":1784},131,[216,1786,957],{"class":654},[216,1788,1789],{"class":226}," (ShortName.",[216,1791,1792],{"class":222},"StartsWith",[216,1794,620],{"class":226},[216,1796,1797],{"class":623},"\"lib\"",[216,1799,1800],{"class":226},")) ",[216,1802,1803],{"class":1126},"\u002F\u002F Without the lib prefix\n",[216,1805,1807],{"class":218,"line":1806},132,[216,1808,632],{"emptyLinePlaceholder":290},[216,1810,1812],{"class":218,"line":1811},133,[216,1813,980],{"class":226},[216,1815,1817],{"class":218,"line":1816},134,[216,1818,632],{"emptyLinePlaceholder":290},[216,1820,1822,1825,1827,1830,1833,1835,1838],{"class":218,"line":1821},135,[216,1823,1824],{"class":226},"                ShortName ",[216,1826,728],{"class":654},[216,1828,1829],{"class":226}," ShortName.",[216,1831,1832],{"class":222},"Substring",[216,1834,620],{"class":226},[216,1836,1837],{"class":1381},"3",[216,1839,627],{"class":226},[216,1841,1843],{"class":218,"line":1842},136,[216,1844,632],{"emptyLinePlaceholder":290},[216,1846,1848],{"class":218,"line":1847},137,[216,1849,1154],{"class":226},[216,1851,1853],{"class":218,"line":1852},138,[216,1854,632],{"emptyLinePlaceholder":290},[216,1856,1858,1861,1864,1867,1870,1872,1875,1879,1882,1885,1888,1890,1893],{"class":218,"line":1857},139,[216,1859,1860],{"class":226},"            ActivityContents.",[216,1862,1863],{"class":222},"Insert",[216,1865,1866],{"class":226},"(LoadLibraryIndex, String.",[216,1868,1869],{"class":222},"Format",[216,1871,620],{"class":226},[216,1873,1874],{"class":623},"\"",[216,1876,1878],{"class":1877},"sAO_F","\\t\\t",[216,1880,1881],{"class":623},"System.loadLibrary(",[216,1883,1884],{"class":1877},"\\\"",[216,1886,1887],{"class":623},"{0}",[216,1889,1884],{"class":1877},[216,1891,1892],{"class":623},");\"",[216,1894,1895],{"class":226},", ShortName));\n",[216,1897,1899],{"class":218,"line":1898},140,[216,1900,632],{"emptyLinePlaceholder":290},[216,1902,1904],{"class":218,"line":1903},141,[216,1905,1328],{"class":226},[216,1907,1909],{"class":218,"line":1908},142,[216,1910,632],{"emptyLinePlaceholder":290},[216,1912,1914],{"class":218,"line":1913},143,[216,1915,1339],{"class":226},[216,1917,1919],{"class":218,"line":1918},144,[216,1920,632],{"emptyLinePlaceholder":290},[216,1922,1924,1927,1930,1933,1936],{"class":218,"line":1923},145,[216,1925,1926],{"class":226},"    File.",[216,1928,1929],{"class":222},"WriteAllLines",[216,1931,1932],{"class":226},"(GameActivityFileName, ActivityContents.",[216,1934,1935],{"class":222},"ToArray",[216,1937,1938],{"class":226},"());\n",[216,1940,1942],{"class":218,"line":1941},146,[216,1943,632],{"emptyLinePlaceholder":290},[216,1945,1947],{"class":218,"line":1946},147,[216,1948,1350],{"class":226},[216,1950,1952],{"class":218,"line":1951},148,[216,1953,632],{"emptyLinePlaceholder":290},[216,1955,1957],{"class":218,"line":1956},149,[216,1958,1959],{"class":1126},"\u002F\u002F PLUGIN DEPLOYMENT END\n",[11,1961,1962],{},"这样一来就可以正常的进行运行工作了，不过由于使用了源码版，有时候编译时间就会比较长了。所以建议在项目打包的时候再进行设置。",[11,1964,1965,1966,553],{},"FMod还有一些其他需要注意的打包事项，例如Bank文件目录等的设定，由于没有使用到那些功能所以没有进行尝试，详情可参照",[216,1967,1968],{},"FMod官方文档",[21,1970,1971],{"id":1971},"目录访问",[11,1973,1974],{},"当前UE4在Android下默认是没有提供访问整个设备的文件的接口的，但是如果是音乐游戏之类的游戏的话，就会需要用到这样的功能。",[11,1976,1977],{},"在AndroidFile.cpp中，我们可以看到，所有的函数都有提供AllowLocal的参数，但是FAndroidPlatformFile在进行IPhysicalPlatformFile的接口实现时使用的却全部是默认的False。AllowLocal参数最终是传递给PathToAndroidPaths这个函数的，因此，直接在该函数中添加",[206,1979,1982],{"className":1980,"code":1981,"language":248},[246],"AllowLocal = true;\n",[213,1983,1981],{"__ignoreMap":211},[11,1985,1986],{},"强制打开本地路径访问即可。同时，这个文件中有开放两个在调试文件访问时比较实用的宏，有需要的时候可以打开",[206,1988,1991],{"className":1989,"code":1990,"language":248},[246],"#define LOG_ANDROID_FILE 1\n#define LOG_ANDROID_FILE_MANIFEST 1\n",[213,1992,1990],{"__ignoreMap":211},[11,1994,1995],{},"另外需要注意的是，FPaths提供的一些函数在Android下并不能很好的运行，经常返回不符合预期的结果。",[11,1997,1998],{},"目前观测到的有",[465,2000,2001,2004,2007],{},[11,2002,2003],{},"FPaths::ConvertRelativePathToFull需要使用IAndroidPlatformFile::GetPlatformPhysical().FileRootPath进行代替",[11,2005,2006],{},"FPaths::GetPath会对根目录返回空字符串",[11,2008,2009],{},"FPaths::IsDrive会对所有的一级目录返回True",[11,2011,2012],{},"使用的时候需要千万注意。",[21,2014,2015],{"id":2015},"功能限制",[11,2017,2018],{},"UE4在移动模式下是有很多功能限制的，如果游戏是面向移动平台的话，最好在添加新功能的时候使用移动平台模拟进行测试，否则到最后就可能真的积重难返了。",[11,2020,2021],{},"目前遇到的限制有：",[465,2023,2024,2027],{},[11,2025,2026],{},"APEX的破碎物体无法作用",[11,2028,2029],{},"部分粒子特效无法显示",[11,2031,2032,2033,553],{},"UE4对移动设备的兼容性也是需要在事先进行调查的，官方的说明在",[333,2034,552],{"href":2035,"rel":2036},"https:\u002F\u002Fdocs.unrealengine.com\u002Flatest\u002FINT\u002FPlatforms\u002FAndroid\u002FDeviceCompatibility\u002Findex.html",[337],[11,2038,2039],{},"引擎自带的示例项目在没有安装第三方插件的情况下，是可以直接通过的，用来测试环境的配置是否正确非常方便。",[11,2041,2042],{},"总体而言UE4的移动端表现还是非常不错的。",[275,2044,2045],{},"html pre.shiki code .s0idv, html code.shiki .s0idv{--shiki-default:#0E1116;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .scAT4, html code.shiki .scAT4{--shiki-default:#622CBC;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html pre.shiki code .sZnmU, html code.shiki .sZnmU{--shiki-default:#032563;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}html pre.shiki code .ss1GH, html code.shiki .ss1GH{--shiki-default:#0E1116;--shiki-default-font-style:inherit;--shiki-dark:#E1E4E8;--shiki-dark-font-style:inherit;--shiki-sepia:#66D9EF;--shiki-sepia-font-style:italic}html pre.shiki code .suI3T, html code.shiki .suI3T{--shiki-default:#702C00;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .sGZGq, html code.shiki .sGZGq{--shiki-default:#A0111F;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit;--shiki-sepia:#66D9EF;--shiki-sepia-font-style:italic}html pre.shiki code .sLXdl, html code.shiki .sLXdl{--shiki-default:#A0111F;--shiki-dark:#F97583;--shiki-sepia:#F92672}html pre.shiki code .sZdD5, html code.shiki .sZdD5{--shiki-default:#66707B;--shiki-dark:#6A737D;--shiki-sepia:#88846F}html pre.shiki code .stP0Q, html code.shiki .stP0Q{--shiki-default:#023B95;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}html pre.shiki code .sAO_F, html code.shiki .sAO_F{--shiki-default:#A0111F;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}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":211,"searchDepth":279,"depth":280,"links":2047},[2048,2049,2050,2051],{"id":544,"depth":279,"text":544},{"id":581,"depth":279,"text":581},{"id":1971,"depth":279,"text":1971},{"id":2015,"depth":279,"text":2015},"2015-08-01",{"layout":288,"status":289,"published":290,"author":2054,"author_login":428,"author_email":429,"author_url":430,"wordpress_id":2055,"wordpress_url":2056,"date_gmt":2057,"excerpt":2058},{"display_name":428,"login":428,"email":429,"url":430},1463,"\u002F\u002F?p=1463","2015-08-01 11:27:14 +0000",{"type":8,"value":2059},[2060],[11,2061,538],{},"\u002F2015-08-01-ue4-package-logs-android",{"title":533,"description":538},"_legacy\u002F2015\u002F2015-08-01-ue4-package-logs-android",[306,2066],"Package","LA841B_nk48EEoA1Vn8rmA1yi-rgmXfVCpbsWXUiUis",{"id":2069,"title":2070,"body":2071,"date":2052,"description":2075,"extension":286,"meta":2181,"navigation":290,"path":2190,"seo":2191,"stem":2192,"tags":2193,"__hash__":2194},"blogs\u002F_legacy\u002F2015\u002F2015-08-01-ue4-package-logs-windows.md","UE4游戏Package记录（Windows）",{"type":8,"value":2072,"toc":2175},[2073,2076,2078,2081,2084,2087,2093,2096,2099,2102,2105,2108,2111,2114,2141,2144,2147,2150,2153,2156,2161,2164,2167,2172],[11,2074,2075],{},"最近对UE4的Package功能进行了使用，整体而言打包功能比想象中复杂一些，限于设备原因只做了Windows和Android的打包。",[11,2077,541],{},[11,2079,2080],{},"面向Windows的打包相对简单，基本只要直接使用即可。",[21,2082,2083],{"id":2083},"视频设定",[11,2085,2086],{},"主要的问题之一是，当前无法在引擎中对游戏的目标分辨率进行设置，在某些情况下会导致打包的效果和PIE的效果相差很大。不过引擎在C++中有提供接口来进行相关的控制，一般在GameMode的BeginPlay中直接调用就可以设置成功了。",[206,2088,2091],{"className":2089,"code":2090,"language":248},[246],"do{\n\n    if(GEngine == nullptr) break;\n\n    UGameUserSettings* Settings = GEngine->GameUserSettings;\n\n    if (Settings == nullptr) break;\n\n    int32 Width = 1920, Height = 1080;\n\n    Settings->RequestResolutionChange(Width, Height, EWindowMode::Type::Windowed, false);\n\n    Settings->ConfirmVideoMode();\n\n    \u002F\u002FSettings->RevertVideoMode(); \u002F\u002F 本操作可以取消分辨率更改\n\n    Settings->SetScreenResolution(Settings->GetLastConfirmedScreenResolution());\n\n    Settings->SetFullscreenMode(Settings->GetLastConfirmedFullscreenMode());\n\n    Settings->SaveSettings();\n\n     Settings->ScalabilityQuality.AntiAliasingQuality = 3;     \u002F\u002F Epic\n\n     Settings->ScalabilityQuality.ResolutionQuality = 3;     \u002F\u002F Epic\n\n    Settings->ApplyNonResolutionSettings();\n\n    Settings->SaveSettings();\n\n}while(false);\n",[213,2092,2090],{"__ignoreMap":211},[11,2094,2095],{},"上面的ScalabilityQuality是可以在编辑器中进行设定的，对应关系如下",[11,2097,2098],{},"另外名为Screen Percentage的属性是在PostProcess的属性中进行设置的。以及，如果要修改抗锯齿的方式，也需要在PostProcess中进行。",[21,2100,2101],{"id":2101},"运行黑屏",[11,2103,2104],{},"打包之后运行直接黑屏的话可能是由很多原因引起的，不过如果是在打包测试的过程中直接使用新项目，或者之前没有进行过设置变更的话，还是可能遇到。原因是没有对默认地图进行设置，主要表现是，完全的黑屏，但是调试输出却可以显示在屏幕上。",[11,2106,2107],{},"在【项目设置>>项目>>地图&模式】中进行修改即可。",[21,2109,2110],{"id":2110},"莫名的链接错误",[11,2112,2113],{},"这个错误的出现几率比较低，而且链接错误有很大的可能性是其他原因引起的，所以排查起来很麻烦。如果之前都是正常的却突然出现类似这样的情况：",[465,2115,2116,2123,2126,2129,2132,2135,2138],{},[11,2117,2118,2119,2122],{},"MainFrameActions: 打包 (Windows (64位)): UnrealBuildTool: ",[216,2120,2121],{},"1\u002F1"," Link Test_mp.exe",[11,2124,2125],{},"MainFrameActions: 打包 (Windows (64位)): UnrealBuildTool:      ڴ      F:\\Unreal\\Test_mp 4.10\\Binaries\\Win64\\Test_mp.lib  Ͷ    F:\\Unreal\\Test_mp 4.10\\Binaries\\Win64\\Test_mp.exp",[11,2127,2128],{},"MainFrameActions: 打包 (Windows (64位)): UnrealBuildTool: UELinkerFixups.cpp.obj : error LNK2019:  ޷        ⲿ     \"void __cdecl EmptyLinkFunctionForGeneratedCodeOnlineSubsystemSteam(void)\" (?EmptyLinkFunctionForGeneratedCodeOnlineSubsystemSteam@@YAXXZ)   ÷    ں    \"void __cdecl UELinkerFixups(void)\" (?UELinkerFixups@@YAXXZ)  б",[11,2130,2131],{},"MainFrameActions: 打包 (Windows (64位)): UnrealBuildTool: UELinkerFixups.cpp.obj : error LNK2019:  ޷        ⲿ     \"void __cdecl EmptyLinkFunctionForStaticInitializationUE4Game(void)\" (?EmptyLinkFunctionForStaticInitializationUE4Game@@YAXXZ)   ÷    ں    \"void __cdecl UELinkerFixups(void)\" (?UELinkerFixups@@YAXXZ)  б",[11,2133,2134],{},"MainFrameActions: 打包 (Windows (64位)): UnrealBuildTool: UELinkerFixups.cpp.obj : error LNK2019:  ޷        ⲿ     \"void __cdecl EmptyLinkFunctionForStaticInitializationOnlineSubsystemNull(void)\" (?EmptyLinkFunctionForStaticInitializationOnlineSubsystemNull@@YAXXZ)   ÷    ں    \"void __cdecl UELinkerFixups(void)\" (?UELinkerFixups@@YAXXZ)  б",[11,2136,2137],{},"MainFrameActions: 打包 (Windows (64位)): UnrealBuildTool: UELinkerFixups.cpp.obj : error LNK2019:  ޷        ⲿ     \"void __cdecl EmptyLinkFunctionForStaticInitializationOnlineSubsystemSteam(void)\" (?EmptyLinkFunctionForStaticInitializationOnlineSubsystemSteam@@YAXXZ)   ÷    ں    \"void __cdecl UELinkerFixups(void)\" (?UELinkerFixups@@YAXXZ)  б",[11,2139,2140],{},"MainFrameActions: 打包 (Windows (64位)): UnrealBuildTool: F:\\Unreal\\Test_mp 4.10\\Binaries\\Win64\\Test_mp.exe : fatal error LNK1120: 4    ޷        ⲿ",[11,2142,2143],{},"可以尝试在打包设定中勾选Full Rebuild",[11,2145,2146],{},"不过需要注意的是，如果使用的是源码版的引擎的话，会消耗大量的时间。",[21,2148,2149],{"id":2149},"杂项记录",[11,2151,2152],{},"打包的过程中还遇到了一些其他的错误，这里姑且记录一下。",[11,2154,2155],{},"在打包完成之后运行游戏始终出现这样的错误：",[465,2157,2158],{},[11,2159,2160],{},"Windows 无法访问指定设备、路径或文件。您可能没有合适的权限访问这个项目。",[11,2162,2163],{},"最后解决办法是把安全软件给关掉，有的安全软件会在没有任何提示的情况下将文件给隔离\u002F删除掉。",[11,2165,2166],{},"还有一个错误是在Ship打包的时候，运行游戏出现错误：",[465,2168,2169],{},[11,2170,2171],{},"Failed to open descriptor file ‘..\u002F..\u002F..\u002FBlank-Win64-Shipping\u002FBlank-Win64-Shipping.uproject’",[11,2173,2174],{},"这个似乎是打包功能的Bug引起的，又或者就是这样的设定。总之将对应的文件名进行修改就可以了，修改运行文件本身的文件名也是可以的。",{"title":211,"searchDepth":279,"depth":280,"links":2176},[2177,2178,2179,2180],{"id":2083,"depth":279,"text":2083},{"id":2101,"depth":279,"text":2101},{"id":2110,"depth":279,"text":2110},{"id":2149,"depth":279,"text":2149},{"layout":288,"status":289,"published":290,"author":2182,"author_login":428,"author_email":429,"author_url":430,"wordpress_id":2183,"wordpress_url":2184,"date_gmt":2185,"excerpt":2186},{"display_name":428,"login":428,"email":429,"url":430},1469,"\u002F\u002F?p=1469","2015-08-01 11:45:05 +0000",{"type":8,"value":2187},[2188],[11,2189,2075],{},"\u002F2015-08-01-ue4-package-logs-windows",{"title":2070,"description":2075},"_legacy\u002F2015\u002F2015-08-01-ue4-package-logs-windows",[306,2066],"LXryStv443cfAY5PNs0jvzqSL3ss1urTELS9PdUjGKg",1788763178377]