[{"data":1,"prerenderedAt":466},["ShallowReactive",2],{"\u002F2022-08-15-ue5-enhanced-input":3},{"id":4,"title":5,"body":6,"date":452,"description":12,"extension":453,"meta":454,"navigation":226,"path":460,"seo":461,"stem":462,"tags":463,"__hash__":465},"blogs\u002F_legacy\u002F2022\u002F2022-08-15-ue5-enhanced-input.md"," UE5 Enhanced input",{"type":7,"value":8,"toc":444},"minimark",[9,13,16,19,35,47,51,54,57,60,71,77,80,84,87,106,109,112,116,123,126,358,365,369,372,385,388,398,403,406,413,416,421,424,429,434,437,440],[10,11,12],"p",{},"最近看Lyra的代码，发现有个新的Enhanced Input系统，稍微看了下。",[10,14,15],{},"当前使用的UE5版本为5.0.3。",[10,17,18],{},"这个系统目前还在实验性阶段，但是看起来官方似乎挺想推的。",[10,20,21,28,29,34],{},[22,23,27],"a",{"href":24,"rel":25},"https:\u002F\u002Fdocs.unrealengine.com\u002F4.27\u002Fen-US\u002FInteractiveExperiences\u002FInput\u002FEnhancedInput\u002F",[26],"nofollow","官方文档","和社区的",[22,30,33],{"href":31,"rel":32},"https:\u002F\u002Fdev.epicgames.com\u002Fcommunity\u002Flearning\u002Ftutorials\u002FaqrD\u002Funreal-engine-enhanced-input-binding-with-gameplay-tags-c",[26],"使用教程","都有比较详尽的描述。",[10,36,37,38,42,43,46],{},"虽然看起来这个系统是为",[39,40,41],"code",{},"GameAbilitySystem","而设计的，且教程那边也用到了",[39,44,45],{},"GamePlayTags","。但是实际上这个系统本身并不强制的使用这两个东西。",[48,49,50],"h2",{"id":50},"简单使用",[10,52,53],{},"基础的配置当然还是要按照官方的来，需要打开插件，然后将输入系统配置到Enhanced Input。",[10,55,56],{},"其实这个系统主要就是将原本只能在项目配置中定义的输入传递给资产化了，方便动态绑定。",[10,58,59],{},"原本在UE4的时候我们要实现动态绑定需要自己做一层中继，现在只是官方给出了可以方便进行动态绑定的部分而已。",[10,61,62,63,66,67,70],{},"核心的部分是",[39,64,65],{},"UInputAction","与",[39,68,69],{},"Input Mapping Contexts","，这两个的使用可以参照上面给出的第二个链接。",[10,72,73,74,76],{},"只不过",[39,75,65],{},"可以直接配置，不需要硬性使用GAS那一套东西。感觉最大的好处是方便项目之间迁移，之前迁移一些逻辑后会发现输入配置对不上。有的时候要到代码和蓝图里面找逻辑中原本绑定的输入到底是什么。输入的配置资产化之后就可以连输入部分一起迁移了。",[10,78,79],{},"当然，有一个官方的动态输入绑定方案自然会方便很多。",[81,82,83],"h3",{"id":83},"输入类型",[10,85,86],{},"这里面个人在测试的时候遗漏了一个地方，就是移动方向这些输入需要修改为Axis2D",[88,89,90,94,97,100,103],"ol",{},[91,92,93],"li",{},"IA_Fire - ValueType(bool), Triggers(Pressed), Modifiers(None)",[91,95,96],{},"IA_Jump - ValueType(bool), Triggers(Pressed ), Modifiers(None) ",[91,98,99],{},"IA_Move - ValueType(Axis2D), Triggers(None ), Modifiers(None ) ",[91,101,102],{},"IA_MouseLook - ValueType(Axis2D), Triggers(None), Modifiers(Negate - Y axis) ",[91,104,105],{},"IA_StickLook - ValueType(Axis2D ), Triggers(None), Modifiers(None)",[10,107,108],{},"如果这里漏掉的话，之后做输入转换的一些2维的操作其实是会失败的。",[10,110,111],{},"表现上会变成只能左右移动无法上下移动，由于原文只有这里没有截图，当时跳过去了。",[81,113,115],{"id":114},"modifier自定义","Modifier自定义",[10,117,118,119,122],{},"修改器虽然可以自定义，但是其实默认的基本够用了。不过需要的时候可以尝试下，很简单的。直接参考引擎的内部实现，继承下",[39,120,121],{},"UInputModifier","就好了。",[10,124,125],{},"需要注意的是InputAction的类型是无法修改的，看引擎的这里：",[127,128,133],"pre",{"className":129,"code":130,"language":131,"meta":132,"style":132},"language-cpp shiki shiki-themes github-light-high-contrast github-dark monokai","FInputActionValue UEnhancedPlayerInput::ApplyModifiers(const TArray\u003CUInputModifier*>& Modifiers, FInputActionValue RawValue, float DeltaTime) const\n{\n    TRACE_CPUPROFILER_EVENT_SCOPE(EnhPIS_Modifiers);\n\n    FInputActionValue ModifiedValue = RawValue;\n    for (UInputModifier* Modifier : Modifiers)\n    {\n        if (Modifier)\n        {\n            \u002F\u002F Enforce that type is kept to RawValue type between modifiers.\n            ModifiedValue = FInputActionValue(RawValue.GetValueType(), Modifier->ModifyRaw(this, ModifiedValue, DeltaTime).Get\u003CFInputActionValue::Axis3D>());\n        }\n    }\n    return ModifiedValue;\n}\n","cpp","",[39,134,135,206,212,221,228,243,259,265,274,280,287,331,337,343,352],{"__ignoreMap":132},[136,137,140,144,147,151,155,158,162,165,168,170,173,176,179,183,186,188,191,193,197,200,203],"span",{"class":138,"line":139},"line",1,[136,141,143],{"class":142},"sfUV7","FInputActionValue",[136,145,146],{"class":142}," UEnhancedPlayerInput",[136,148,150],{"class":149},"s0idv","::",[136,152,154],{"class":153},"scAT4","ApplyModifiers",[136,156,157],{"class":149},"(",[136,159,161],{"class":160},"sLXdl","const",[136,163,164],{"class":142}," TArray",[136,166,167],{"class":149},"\u003C",[136,169,121],{"class":142},[136,171,172],{"class":160},"*",[136,174,175],{"class":149},">",[136,177,178],{"class":160},"&",[136,180,182],{"class":181},"sbfHu"," Modifiers",[136,184,185],{"class":149},", ",[136,187,143],{"class":142},[136,189,190],{"class":181}," RawValue",[136,192,185],{"class":149},[136,194,196],{"class":195},"sGZGq","float",[136,198,199],{"class":181}," DeltaTime",[136,201,202],{"class":149},") ",[136,204,205],{"class":160},"const\n",[136,207,209],{"class":138,"line":208},2,[136,210,211],{"class":149},"{\n",[136,213,215,218],{"class":138,"line":214},3,[136,216,217],{"class":153},"    TRACE_CPUPROFILER_EVENT_SCOPE",[136,219,220],{"class":149},"(EnhPIS_Modifiers);\n",[136,222,224],{"class":138,"line":223},4,[136,225,227],{"emptyLinePlaceholder":226},true,"\n",[136,229,231,234,237,240],{"class":138,"line":230},5,[136,232,233],{"class":142},"    FInputActionValue",[136,235,236],{"class":149}," ModifiedValue ",[136,238,239],{"class":160},"=",[136,241,242],{"class":149}," RawValue;\n",[136,244,246,249,252,254,256],{"class":138,"line":245},6,[136,247,248],{"class":160},"    for",[136,250,251],{"class":149}," (",[136,253,121],{"class":142},[136,255,172],{"class":160},[136,257,258],{"class":149}," Modifier : Modifiers)\n",[136,260,262],{"class":138,"line":261},7,[136,263,264],{"class":149},"    {\n",[136,266,268,271],{"class":138,"line":267},8,[136,269,270],{"class":160},"        if",[136,272,273],{"class":149}," (Modifier)\n",[136,275,277],{"class":138,"line":276},9,[136,278,279],{"class":149},"        {\n",[136,281,283],{"class":138,"line":282},10,[136,284,286],{"class":285},"sZdD5","            \u002F\u002F Enforce that type is kept to RawValue type between modifiers.\n",[136,288,290,293,295,298,301,304,307,310,312,316,319,321,323,326,328],{"class":138,"line":289},11,[136,291,292],{"class":149},"            ModifiedValue ",[136,294,239],{"class":160},[136,296,297],{"class":153}," FInputActionValue",[136,299,300],{"class":149},"(RawValue.",[136,302,303],{"class":153},"GetValueType",[136,305,306],{"class":149},"(), Modifier->",[136,308,309],{"class":153},"ModifyRaw",[136,311,157],{"class":149},[136,313,315],{"class":314},"s4Wjf","this",[136,317,318],{"class":149},", ModifiedValue, DeltaTime).Get",[136,320,167],{"class":160},[136,322,143],{"class":142},[136,324,325],{"class":149},"::Axis3D",[136,327,175],{"class":160},[136,329,330],{"class":149},"());\n",[136,332,334],{"class":138,"line":333},12,[136,335,336],{"class":149},"        }\n",[136,338,340],{"class":138,"line":339},13,[136,341,342],{"class":149},"    }\n",[136,344,346,349],{"class":138,"line":345},14,[136,347,348],{"class":160},"    return",[136,350,351],{"class":149}," ModifiedValue;\n",[136,353,355],{"class":138,"line":354},15,[136,356,357],{"class":149},"}\n",[10,359,360,361,364],{},"就算在修改器里面改了，在这里也会被设置回到",[39,362,363],{},"RawValue.GetValueType()","。",[48,366,368],{"id":367},"commonui问题","CommonUI问题",[10,370,371],{},"CommonUI这边有一个全局的Action绑定，但是配置好之后使用的过程中总是会报错。",[373,374,375],"blockquote",{},[10,376,377,378,381,382,384],{},"\"Cannot\nbind widget ",[136,379,380],{},"%s"," to action ",[136,383,380],{}," - provided tag does not map to an existing UI\ninput action. It can be added under Project Settings->UI Input.",[10,386,387],{},"排查了下原因，感觉是实验性阶段的BUG。主要的问题来源是：",[10,389,390,393,394,397],{},[39,391,392],{},"UCommonUIInputSettings","的加载时机要早于",[39,395,396],{},"FGlobalUITags","的标签加载时机",[373,399,400],{},[10,401,402],{},"UGameplayTagsManager::OnLastChanceToAddNativeTags",[10,404,405],{},"导致在配置加载的时候没有读取到Tag，最后绑定的时候就错了。",[10,407,408,409,412],{},"倒腾了下没发现好的直接修正的方式，只能通过自己定义Tag的方式来绕过。自己定义Tag可以选择直接在项目配置里面加。如果一时之间找不到配置的位置，在项目配置里面搜索",[39,410,411],{},"gameplay tags","即可。",[10,414,415],{},"或者在代码中快速定义：",[373,417,418],{},[10,419,420],{},"UE_DEFINE_GAMEPLAY_TAG_STATIC(Tag_CUSTOM_SETTINGS_INPUT_ACTION_Cancel, \"UI.Action.Css.Cancel\");",[10,422,423],{},"也可以通过.h与.cpp中分别定义来方便别的类能够取到",[373,425,426],{},[10,427,428],{},"UE_DECLARE_GAMEPLAY_TAG_EXTERN(Tag_CUSTOM_SETTINGS_INPUT_ACTION_Confrim);",[373,430,431],{},[10,432,433],{},"UE_DEFINE_GAMEPLAY_TAG(Tag_CUSTOM_SETTINGS_INPUT_ACTION_Confrim, \"UI.Action.Css.Confirm\")",[48,435,436],{"id":436},"总结",[10,438,439],{},"总体而言感觉新系统的意义不是很大，如果项目中已有完整的输入管理逻辑的话，没有必要迁移。可能对新项目可以考虑下……",[441,442,443],"style",{},"html pre.shiki code .sfUV7, html code.shiki .sfUV7{--shiki-default:#702C00;--shiki-default-text-decoration:inherit;--shiki-dark:#B392F0;--shiki-dark-text-decoration:inherit;--shiki-sepia:#A6E22E;--shiki-sepia-text-decoration:underline}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 .sLXdl, html code.shiki .sLXdl{--shiki-default:#A0111F;--shiki-dark:#F97583;--shiki-sepia:#F92672}html pre.shiki code .sbfHu, html code.shiki .sbfHu{--shiki-default:#702C00;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit;--shiki-sepia:#FD971F;--shiki-sepia-font-style:italic}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 .sZdD5, html code.shiki .sZdD5{--shiki-default:#66707B;--shiki-dark:#6A737D;--shiki-sepia:#88846F}html pre.shiki code .s4Wjf, html code.shiki .s4Wjf{--shiki-default:#023B95;--shiki-dark:#79B8FF;--shiki-sepia:#FD971F}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":132,"searchDepth":208,"depth":214,"links":445},[446,450,451],{"id":50,"depth":208,"text":50,"children":447},[448,449],{"id":83,"depth":214,"text":83},{"id":114,"depth":214,"text":115},{"id":367,"depth":208,"text":368},{"id":436,"depth":208,"text":436},"2022-08-15","md",{"layout":455,"excerpt":456},"post",{"type":7,"value":457},[458],[10,459,12],{},"\u002F2022-08-15-ue5-enhanced-input",{"title":5,"description":12},"_legacy\u002F2022\u002F2022-08-15-ue5-enhanced-input",[464],"UE5","14nYQPYf3R6xkEirhewjHWl0UU3aYeXZM60t9GxwqAc",1788763176836]