[{"data":1,"prerenderedAt":309},["ShallowReactive",2],{"page-事件调度器-1":3,"page-count-事件调度器":219},[4],{"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",1788763180338]