[{"data":1,"prerenderedAt":395},["ShallowReactive",2],{"\u002Fblogs\u002F2026\u002Fue5-interface-note":3},{"id":4,"title":5,"body":6,"date":381,"description":12,"extension":382,"meta":383,"navigation":237,"path":389,"seo":390,"stem":391,"tags":392,"__hash__":394},"blogs\u002Fblogs\u002F2026\u002Fue5-interface-note.md","UE5中UInterface使用备忘",{"type":7,"value":8,"toc":369},"minimark",[9,13,24,28,36,41,44,74,85,89,92,109,112,118,122,128,173,176,179,182,300,311,314,317,320,330,333,340,343,346,352,356,365],[10,11,12],"p",{},"UInterface这个系统其实UE4就有，只是一些相关的东西每次都会不小心踩坑。",[10,14,15,16,23],{},"接口的官方文档是这个: ",[17,18,22],"a",{"href":19,"rel":20},"https:\u002F\u002Fdev.epicgames.com\u002Fdocumentation\u002Fzh-cn\u002Funreal-engine\u002Finterfaces-in-unreal-engine",[21],"nofollow","Unreal Interfaces","。",[25,26,27],"h2",{"id":27},"指针容器",[10,29,30,31,35],{},"官方有提供一些接口的指针容器，可以更方便的对接口指针进行存储，比保存",[32,33,34],"code",{},"UObject","指针然后每次检查和转换方便很多。",[37,38,40],"h3",{"id":39},"tweakinterfaceptr","TWeakInterfacePtr",[10,42,43],{},"弱指针，不能作为蓝图属性。",[45,46,51],"pre",{"className":47,"code":48,"language":49,"meta":50,"style":50},"language-cpp shiki shiki-themes github-light-high-contrast github-dark monokai","TWeakInterfacePtr\u003CIMyAwsomeInteface> MyPtr;\n","cpp","",[32,52,53],{"__ignoreMap":50},[54,55,58,61,65,68,71],"span",{"class":56,"line":57},"line",1,[54,59,40],{"class":60},"s0idv",[54,62,64],{"class":63},"sLXdl","\u003C",[54,66,67],{"class":60},"IMyAwsomeInteface",[54,69,70],{"class":63},">",[54,72,73],{"class":60}," MyPtr;\n",[10,75,76,77,80,81,84],{},"但是有提供",[32,78,79],{},"TWeakObjectPtr","一样的",[32,82,83],{},"IsValid","封装，在C++逻辑中比较实用。",[37,86,88],{"id":87},"tscriptinterface","TScriptInterface",[10,90,91],{},"可以作为蓝图属性存在。",[45,93,95],{"className":47,"code":94,"language":49,"meta":50,"style":50},"TScriptInterface\u003CIMyAwsomeInteface> MyPtr;\n",[32,96,97],{"__ignoreMap":50},[54,98,99,101,103,105,107],{"class":56,"line":57},[54,100,88],{"class":60},[54,102,64],{"class":63},[54,104,67],{"class":60},[54,106,70],{"class":63},[54,108,73],{"class":60},[10,110,111],{},"目前无法兼容在蓝图中继承的情况。可以参照官方的类注释",[113,114,115],"blockquote",{},[10,116,117],{},"This type is only useful with native interfaces, UClass::ImplementsInterface should be used to check for blueprint interfaces.",[37,119,121],{"id":120},"mustimplement","MustImplement",[10,123,124,125,127],{},"可以通过",[32,126,121],{},"标签来要求指针必须实现接口",[45,129,131],{"className":47,"code":130,"language":49,"meta":50,"style":50},"UPROPERTY(meta=(MustImplement =\"\u002FScript\u002FMyAwusomeModule.MyAwsomeInteface\"))\nTObjectPtr\u003CAActor> MyActor;\n",[32,132,133,157],{"__ignoreMap":50},[54,134,135,139,142,145,148,150,154],{"class":56,"line":57},[54,136,138],{"class":137},"scAT4","UPROPERTY",[54,140,141],{"class":60},"(meta",[54,143,144],{"class":63},"=",[54,146,147],{"class":60},"(MustImplement ",[54,149,144],{"class":63},[54,151,153],{"class":152},"sZnmU","\"\u002FScript\u002FMyAwusomeModule.MyAwsomeInteface\"",[54,155,156],{"class":60},"))\n",[54,158,160,163,165,168,170],{"class":56,"line":159},2,[54,161,162],{"class":60},"TObjectPtr",[54,164,64],{"class":63},[54,166,167],{"class":60},"AActor",[54,169,70],{"class":63},[54,171,172],{"class":60}," MyActor;\n",[10,174,175],{},"即便是在蓝图中实现的接口也能兼容，对于从关卡中选择物品的情况比较有用，可以有效的防止选错。",[25,177,178],{"id":178},"指针转换",[10,180,181],{},"通常情况下，在需要做指针转换时，有以下三种方法",[45,183,185],{"className":47,"code":184,"language":49,"meta":50,"style":50},"\u002F** 如果OriginalObject实现了UMyAwsomeInterface，则bisimplemated将为true。*\u002F\nbool bIsImplemented = OriginalObject->GetClass()->ImplementsInterface(UMyAwsomeInterface::StaticClass()); \n\n\u002F** 如果OriginalObject实现了UReactToTrigger，bIsImplemented将为true。 *\u002F\nbIsImplemented = OriginalObject->Implements\u003CUMyAwsomeInterface>(); \n\n\u002F** 如果OriginalObject实现了UMyAwsomeInterface，则RCastedInterfaceObject将为非空。 *\u002F\nIMyAwsomeInterface* CastedInterfaceObject = Cast\u003CIMyAwsomeInterface>(OriginalObject); \n",[32,186,187,193,232,239,245,265,270,276],{"__ignoreMap":50},[54,188,189],{"class":56,"line":57},[54,190,192],{"class":191},"sZdD5","\u002F** 如果OriginalObject实现了UMyAwsomeInterface，则bisimplemated将为true。*\u002F\n",[54,194,195,199,202,204,207,210,213,216,219,223,226,229],{"class":56,"line":159},[54,196,198],{"class":197},"sGZGq","bool",[54,200,201],{"class":60}," bIsImplemented ",[54,203,144],{"class":63},[54,205,206],{"class":60}," OriginalObject->",[54,208,209],{"class":137},"GetClass",[54,211,212],{"class":60},"()->",[54,214,215],{"class":137},"ImplementsInterface",[54,217,218],{"class":60},"(",[54,220,222],{"class":221},"sfUV7","UMyAwsomeInterface",[54,224,225],{"class":60},"::",[54,227,228],{"class":137},"StaticClass",[54,230,231],{"class":60},"()); \n",[54,233,235],{"class":56,"line":234},3,[54,236,238],{"emptyLinePlaceholder":237},true,"\n",[54,240,242],{"class":56,"line":241},4,[54,243,244],{"class":191},"\u002F** 如果OriginalObject实现了UReactToTrigger，bIsImplemented将为true。 *\u002F\n",[54,246,248,251,253,256,258,260,262],{"class":56,"line":247},5,[54,249,250],{"class":60},"bIsImplemented ",[54,252,144],{"class":63},[54,254,255],{"class":60}," OriginalObject->Implements",[54,257,64],{"class":63},[54,259,222],{"class":60},[54,261,70],{"class":63},[54,263,264],{"class":60},"(); \n",[54,266,268],{"class":56,"line":267},6,[54,269,238],{"emptyLinePlaceholder":237},[54,271,273],{"class":56,"line":272},7,[54,274,275],{"class":191},"\u002F** 如果OriginalObject实现了UMyAwsomeInterface，则RCastedInterfaceObject将为非空。 *\u002F\n",[54,277,279,282,285,288,290,293,295,297],{"class":56,"line":278},8,[54,280,281],{"class":60},"IMyAwsomeInterface",[54,283,284],{"class":63},"*",[54,286,287],{"class":60}," CastedInterfaceObject ",[54,289,144],{"class":63},[54,291,292],{"class":137}," Cast",[54,294,64],{"class":60},[54,296,281],{"class":221},[54,298,299],{"class":60},">(OriginalObject);\n",[10,301,302,303,306,307,310],{},"按照官方的说法，这三个接口是等价的。\n但是实际情况是，如果接口是在蓝图中继承的话，会出现：",[32,304,305],{},"Cast\u003CIMyAwsomeInteface>(IterActor)","返回空，但是",[32,308,309],{},"IterActor->Implements\u003CUMyAwsomeInteface>()","却成功的情况。",[10,312,313],{},"如果制作逻辑的时候没有留意到的话，很可能会出现一些不在预期中的情况。",[37,315,316],{"id":316},"安全的方法",[10,318,319],{},"以下的调用方法是基本安全的：",[321,322,323,327],"ol",{},[324,325,326],"li",{},"使用Implements检查指针是否实现了接口",[324,328,329],{},"IMyAwsomeInteface::Execute_MyAwsomeFunction",[37,331,332],{"id":332},"指针自动转换",[10,334,335,336,339],{},"帮助类指针自动转换并不会提供一个绕过",[32,337,338],{},"IMyAwsomeInteface::Execute_","的机会，当前其实和手动Cast然后赋值给帮助类是一样的。",[10,341,342],{},"基本可以将蓝图实现接口和直接在代码中继承使用的接口当作两种情况来看待：",[10,344,345],{},"将UInterface当作一种提供转换帮助类的C++层接口封装的时候，使用起来会比较随意。",[10,347,348,349,351],{},"如果接口会在蓝图中使用，则基本上使用",[32,350,338],{},"系列会比较安全。",[37,353,355],{"id":354},"doesimplementinterface","DoesImplementInterface",[10,357,358,361,362,364],{},[32,359,360],{},"UKismetSystemLibrary::DoesImplementInterface","是官方提供的帮助类，其实是对",[32,363,215],{},"的封装，则基本可以等效对待。",[366,367,368],"style",{},"html pre.shiki code .s0idv, html code.shiki .s0idv{--shiki-default:#0E1116;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .sLXdl, html code.shiki .sLXdl{--shiki-default:#A0111F;--shiki-dark:#F97583;--shiki-sepia:#F92672}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);}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 .sZdD5, html code.shiki .sZdD5{--shiki-default:#66707B;--shiki-dark:#6A737D;--shiki-sepia:#88846F}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 .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}",{"title":50,"searchDepth":159,"depth":234,"links":370},[371,376],{"id":27,"depth":159,"text":27,"children":372},[373,374,375],{"id":39,"depth":234,"text":40},{"id":87,"depth":234,"text":88},{"id":120,"depth":234,"text":121},{"id":178,"depth":159,"text":178,"children":377},[378,379,380],{"id":316,"depth":234,"text":316},{"id":332,"depth":234,"text":332},{"id":354,"depth":234,"text":355},"2026-09-09","md",{"layout":384,"excerpt":385},"post",{"type":7,"value":386},[387],[10,388,12],{},"\u002Fblogs\u002F2026\u002Fue5-interface-note",{"title":5,"description":12},"blogs\u002F2026\u002Fue5-interface-note",[393],"UE5","aQWUSHU-nWeo9hNfvyYLOYn7asKVr3Go-XGr3URcSHk",1789292571382]