{"id":4108,"date":"2024-03-30T00:57:46","date_gmt":"2024-03-29T16:57:46","guid":{"rendered":"https:\/\/lonelinerd.com\/?p=4108"},"modified":"2024-03-30T01:13:26","modified_gmt":"2024-03-29T17:13:26","slug":"ue5_ai_bt_decorator_node","status":"publish","type":"post","link":"https:\/\/lonelinerd.com\/index.php\/2024\/03\/30\/ue5_ai_bt_decorator_node\/","title":{"rendered":"[C++\/UE] UE5\u4e2dAI\u958b\u767c\u7684\u4e00\u9ede\u529f\u80fd\u68b3\u7406\uff08\u4e09\uff09 \u2013 \u884c\u70ba\u6a39Decorator\u985e\u578b\u7bc0\u9ede\u8aaa\u660e"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"4108\" class=\"elementor elementor-4108\">\n\t\t\t\t\t\t<div class=\"elementor-inner\">\n\t\t\t\t<div class=\"elementor-section-wrap\">\n\t\t\t\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-9325268 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"9325268\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-423ff9a\" data-id=\"423ff9a\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-e404f39 elementor-widget elementor-widget-text-editor\" data-id=\"e404f39\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<h3><span style=\"text-decoration: underline;\"><strong>\u884c\u70ba\u6a39Decorator\u7bc0\u9ede\u8aaa\u660e<\/strong><\/span><\/h3><ul><li>\u7528\u65bc\u6c7a\u5b9a\u7bc0\u9ede\u80fd\u5426\u57f7\u884c\/ \u5c0d\u7bc0\u9ede\u7684\u8fd4\u56de\u7d50\u679c\u9032\u884c\u4fee\u6539\uff0cCompositie\u7bc0\u9ede\u548cTask\u7bc0\u9ede\u4e0a\u90fd\u53ef\u4ee5\u6dfb\u52a0<ul><li>\u53f3\u9375\u7bc0\u9ede -&gt; Add Decorator<\/li><\/ul><\/li><\/ul>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-32eb5a6 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"32eb5a6\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-34ca2df\" data-id=\"34ca2df\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-852b02c elementor-widget-divider--view-line elementor-widget elementor-widget-divider\" data-id=\"852b02c\" data-element_type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"elementor-divider\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-db6e86e elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"db6e86e\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-16bdfe9\" data-id=\"16bdfe9\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-b4196e0 elementor-widget elementor-widget-text-editor\" data-id=\"b4196e0\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<h4><strong><u>\u5167\u7f6eDecorator<\/u><\/strong><\/h4><ul><li><strong>Blackboard<\/strong>\uff1a\u5224\u65b7blackboard\u88e1\u67d0Key\u7684\u503c\u7684\u72c0\u614b<\/li><\/ul>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-40386b9 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"40386b9\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-93e6346\" data-id=\"93e6346\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-b36a760 elementor-widget elementor-widget-image\" data-id=\"b36a760\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-image\">\n\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"553\" height=\"232\" src=\"https:\/\/lonelinerd.com\/wp-content\/uploads\/2024\/03\/BlackboardDecorator.png\" class=\"attachment-large size-large wp-image-4111\" alt=\"\" srcset=\"https:\/\/lonelinerd.com\/wp-content\/uploads\/2024\/03\/BlackboardDecorator.png 553w, https:\/\/lonelinerd.com\/wp-content\/uploads\/2024\/03\/BlackboardDecorator-300x126.png 300w\" sizes=\"auto, (max-width: 553px) 100vw, 553px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-04d8b2c elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"04d8b2c\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-08eac82\" data-id=\"08eac82\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-6b60a8c elementor-widget elementor-widget-text-editor\" data-id=\"6b60a8c\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<ul><li><strong>Check Gameplay Tags On Actor<\/strong>\uff1a\u5224\u65b7blackboard\u88e1\u67d0\u500bActor\u985e\u578bKey\u7684Gameplay Tags<\/li><li><strong>Compare BBEntries<\/strong>\uff1a\u5c0dblackboard\u88e1\u7684\u5169\u500bKey\u9032\u884c\u6bd4\u8f03<\/li><li><strong>Composite<\/strong>\uff1a\u7d44\u5408Decorator\u85cd\u5716\uff0c\u53ef\u4ee5\u81ea\u5b9a\u7fa9\u6dfb\u52a0\u591a\u500bDecorator\u53caAnd\/Or\/Not\u7d44\u5408\u6210\u4e00\u500b\u8907\u5408\u689d\u4ef6Decorator<\/li><\/ul>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-836c7d4 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"836c7d4\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-d01cfe7\" data-id=\"d01cfe7\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-470b0d0 elementor-widget elementor-widget-image\" data-id=\"470b0d0\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-image\">\n\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"553\" height=\"244\" src=\"https:\/\/lonelinerd.com\/wp-content\/uploads\/2024\/03\/CompositeDecorator.png\" class=\"attachment-large size-large wp-image-4112\" alt=\"\" srcset=\"https:\/\/lonelinerd.com\/wp-content\/uploads\/2024\/03\/CompositeDecorator.png 553w, https:\/\/lonelinerd.com\/wp-content\/uploads\/2024\/03\/CompositeDecorator-300x132.png 300w\" sizes=\"auto, (max-width: 553px) 100vw, 553px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-f4daf0c elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"f4daf0c\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-b0d263a\" data-id=\"b0d263a\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-90a1306 elementor-widget elementor-widget-text-editor\" data-id=\"90a1306\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<ul><li><strong>Conditional Loop<\/strong>\uff1a\u9ed1\u677f\u7684\u67d0\u500bKey\u7b26\u5408\u689d\u4ef6\u5c31\u4e00\u76f4\u5faa\u74b0<\/li><li><strong>Cone Check<\/strong>\uff1a\u5f9eCone Origin\u958b\u59cb\uff0c\u5f80Cone Direction\u5efa\u7acb\u4e00\u500b\u534a\u89d2\u70baCone Half Angle\u7684\u8996\u9310\uff0c\u5224\u65b7Observed\u662f\u5426\u5728\u8996\u9310\u7bc4\u570d\u88e1<\/li><li><strong>Cooldown<\/strong>\uff1a\u9032\u5165\u7bc0\u9ede\u5f8c\uff0c\u6703\u958b\u59cb\u6307\u5b9a\u6642\u9593\u7684\u8a08\u6642\uff0c\u5728\u8a08\u6642\u7d50\u675f\u524d\u6bcf\u6b21\u5617\u8a66\u9032\u5165\u8a72\u7bc0\u9ede\uff0c\u90fd\u6703\u76f4\u63a5\u8fd4\u56de<\/li><li><strong>Does Path Exist<\/strong>: \u5224\u65b7\u9ed1\u677f\u4e2d\u7684\u5169\u500bActor Key\u4e4b\u9593\u662f\u5426\u6709\u53ef\u5c0b\u8def\u5f91<ul><li>Path Query Type\uff1a<ul><li>Navmesh Raycast 2D \u6700\u5feb\uff0c\u4f7f\u7528NavMesh\u7db2\u683c\u7684\u6578\u64da\u9032\u884c\u5c0b\u8def<\/li><li>Hierarchical Query \/ Regular Pathfinding \u90fd\u6bd4\u8f03\u6162\uff0c\u4f7f\u7528UE\u7684\u53e6\u4e00\u5957\u7684\u5c0b\u8def\u7b97\u6cd5\u9032\u884c\u5c0b\u8def<\/li><\/ul><\/li><\/ul><\/li><\/ul>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-39d88cd elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"39d88cd\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-2f12ff0\" data-id=\"2f12ff0\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-33b6681 elementor-widget elementor-widget-code-block-for-elementor\" data-id=\"33b6681\" data-element_type=\"widget\" data-widget_type=\"code-block-for-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<pre class='line-numbers theme-okaidia' data-show-toolbar='yes'><code class='language-cpp'>\/\/BTDecorator_DoesPathExist.cpp\r\n\r\nbool UBTDecorator_DoesPathExist::CalculateRawConditionValue(UBehaviorTreeComponent&amp; OwnerComp, uint8* NodeMemory) const\r\n{\r\n    const UBlackboardComponent* BlackboardComp = OwnerComp.GetBlackboardComponent();\r\n    if (BlackboardComp == NULL)\r\n    {\r\n        return false;\r\n    }\r\n\r\n    FVector PointA = FVector::ZeroVector;\r\n    FVector PointB = FVector::ZeroVector;    \r\n    const bool bHasPointA = BlackboardComp-&gt;GetLocationFromEntry(BlackboardKeyA.GetSelectedKeyID(), PointA);\r\n    const bool bHasPointB = BlackboardComp-&gt;GetLocationFromEntry(BlackboardKeyB.GetSelectedKeyID(), PointB);\r\n    \r\n    bool bHasPath = false;\r\n\r\n    const UNavigationSystemV1* NavSys = FNavigationSystem::GetCurrent&lt;UNavigationSystemV1&gt;(OwnerComp.GetWorld());\r\n    if (NavSys &amp;&amp; bHasPointA &amp;&amp; bHasPointB)\r\n    {\r\n        const AAIController* AIOwner = OwnerComp.GetAIOwner();\r\n        const ANavigationData* NavData = AIOwner ? NavSys-&gt;GetNavDataForProps(AIOwner-&gt;GetNavAgentPropertiesRef(), AIOwner-&gt;GetNavAgentLocation()) : NULL;\r\n        if (NavData)\r\n        {\r\n            FSharedConstNavQueryFilter QueryFilter = UNavigationQueryFilter::GetQueryFilter(*NavData, AIOwner, FilterClass);\r\n\r\n            if (PathQueryType == EPathExistanceQueryType::NavmeshRaycast2D)\r\n            {\r\n#if WITH_RECAST\r\n                const ARecastNavMesh* RecastNavMesh = Cast&lt;const ARecastNavMesh&gt;(NavData);\r\n                bHasPath = RecastNavMesh &amp;&amp; RecastNavMesh-&gt;IsSegmentOnNavmesh(PointA, PointB, QueryFilter);\r\n#endif\r\n            }\r\n            else\r\n            {\r\n                EPathFindingMode::Type TestMode = (PathQueryType == EPathExistanceQueryType::HierarchicalQuery) ? EPathFindingMode::Hierarchical : EPathFindingMode::Regular;\r\n                bHasPath = NavSys-&gt;TestPathSync(FPathFindingQuery(AIOwner, *NavData, PointA, PointB, QueryFilter), TestMode);\r\n            }\r\n        }\r\n    }\r\n\r\n    return bHasPath;\r\n}\r\n\r\n\/\/NavigationSystem.cpp\r\nbool UNavigationSystemV1::TestPathSync(FPathFindingQuery Query, EPathFindingMode::Type Mode, int32* NumVisitedNodes) const\r\n{\r\n    SCOPE_CYCLE_COUNTER(STAT_Navigation_PathfindingSync);\r\n    CSV_SCOPED_TIMING_STAT(NavigationSystem, PathfindingSync);\r\n\r\n    if (Query.NavData.IsValid() == false)\r\n    {\r\n        Query.NavData = GetDefaultNavDataInstance();\r\n    }\r\n    \r\n    bool bExists = false;\r\n    if (Query.NavData.IsValid())\r\n    {\r\n        if (Mode == EPathFindingMode::Hierarchical)\r\n        {\r\n            bExists = Query.NavData-&gt;TestHierarchicalPath(Query.NavAgentProperties, Query, NumVisitedNodes);\r\n        }\r\n        else\r\n        {\r\n            bExists = Query.NavData-&gt;TestPath(Query.NavAgentProperties, Query, NumVisitedNodes);\r\n        }\r\n    }\r\n\r\n    return bExists;\r\n}\r\n<\/code><\/pre>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-4cf6ed2 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"4cf6ed2\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-0d5aaee\" data-id=\"0d5aaee\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-bbd6c4a elementor-widget elementor-widget-text-editor\" data-id=\"bbd6c4a\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<ul><li><strong>Force Success<\/strong>: \u7bc0\u9ede\u8fd4\u56de\u503c\u4fee\u6539\u70batrue<\/li><li><strong>Is At Location<\/strong>\uff1a\u5224\u65b7\u7576\u524d\u4f4d\u7f6e\u662f\u5426\u5728blackboard\u7684\u67d0\u500bVector key\u7684\u6307\u5b9a\u534a\u5f91\u7bc4\u570d\u5167<ul><li>Inverse Condition\uff1a\u5224\u65b7\u662f\u5426\u4e0d\u5728\u7bc4\u570d\u5167<\/li><li>\u53ef\u4ee5\u7528\u4f86\u505a\u4e00\u4e9b\u653b\u6483\/\u4ea4\u4e92\u53ef\u884c\u6027\u7684\u5224\u65b7<\/li><\/ul><\/li><li><strong>Is BBEntry Of Class<\/strong>\uff1a\u6aa2\u67e5blackboard\u88e1\u7684\u67d0\u500bObject\u662f\u5426\u70ba\u6307\u5b9a\u985e\u578b<\/li><li><strong>Keep in Cone<\/strong>\uff1a\u5224\u65b7\u67d0\u88ab\u89c0\u5bdf\u5c0d\u8c61\u662f\u5426\u5728\u67d0\u89c0\u5bdf\u8005\u5c0d\u8c61\u7684\u8996\u9310\u7bc4\u570d\u5167\uff0c\u534a\u89d2\u53ef\u6307\u5b9a<\/li><li><strong>Loop<\/strong>\uff1a\u5faa\u74b0\u6b21\u6578\uff0c\u5224\u65b7\u67d0\u500b\u7bc0\u9ede\u7684\u9032\u5165\u6b21\u6578\u662f\u5426 &lt; Num Loops<\/li><li><strong>Set Tag Cooldown \/ Tag Cooldown<\/strong>\uff1a\u7d66\u6307\u5b9aGameplay Tag\u8a2d\u7f6e\u51b7\u537b\u6642\u9593\uff0c\u5177\u9ad4\u5224\u5b9a\u908f\u8f2f\u8207Cooldown\u4e00\u6a23<\/li><li><strong>Time Limit<\/strong>\uff1a\u5c0d\u7bc0\u9ede\u7684\u904b\u884c\u6642\u9593\u589e\u52a0\u6642\u9593\u9650\u5236\uff0c\u7bc0\u9ede\u904b\u884c\u8d85\u6642\u5f8c\u8fd4\u56deFailed\uff0c\u6bcf\u6b21\u9032\u5165\u7bc0\u9ede\u6642\u8a08\u6642\u5668\u90fd\u6703\u91cd\u7f6e<\/li><\/ul>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-a979e74 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"a979e74\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-fc0297c\" data-id=\"fc0297c\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-f4d4198 elementor-widget-divider--view-line elementor-widget elementor-widget-divider\" data-id=\"f4d4198\" data-element_type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"elementor-divider\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-c758e0c elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"c758e0c\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-324b320\" data-id=\"324b320\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-2ba3ff3 elementor-widget elementor-widget-text-editor\" data-id=\"2ba3ff3\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<h4><span style=\"text-decoration: underline;\"><strong>\u81ea\u5b9a\u7fa9Decorator<\/strong><\/span><\/h4><ul><li>\u884c\u70ba\u6a39\u4e0a\u65b9 -&gt; New Decorator<\/li><li>Decorator\u85cd\u5716\u63d0\u4f9b\u4e865\u5f0f10\u7a2e\u4e8b\u4ef6\u51fd\u6578\u548c1\u5f0f2\u7a2e\u7684\u4e00\u822c\u51fd\u6578\u91cd\u8f09\uff0c\u6700\u91cd\u8981\u7684\u5c31\u662f\u9019\u500b\u4e00\u822c\u51fd\u6578 Perform Condition Check\uff0c\u5176\u4ed6\u90fd\u662f\u4e00\u4e9b\u6642\u6a5f\u4e8b\u4ef6\u3002\u4e14\u5e36AI\u5f8c\u7db4\u7684\u624d\u80fd\u62ff\u5230AI Controller\uff0c\u5426\u5247\u53ea\u80fd\u62ff\u5230Actor\u00a0<ul><li><strong>Receive Execution Finish\uff08AI\uff09<\/strong>\uff1a\u4f9d\u9644\u7684Task\u7bc0\u9ede\u57f7\u884c\u5b8c\u6210<\/li><li><strong>Receive Execution Start\uff08AI\uff09<\/strong>\uff1a\u4f9d\u9644\u7684Task\u7bc0\u9ede\u958b\u59cb\u57f7\u884c<\/li><li><strong>Receive Observer Activated\uff08AI\uff09 (Deactivated\uff08AI\uff09)<\/strong><ul><li>Observer\u6307\u7684abort observer\u7684observer<\/li><li><strong>abort observer == self<\/strong><ul><li>observer\u70ba\u7576\u524d\u5b50\u6a39<\/li><li>observer activated\uff1a\u7576\u524d\u57f7\u884c\u4fdd\u7559\u5728\u5b50\u6a39\u6642\u6fc0\u6d3b<\/li><li>deactivated: \u7576\u524d\u57f7\u884c\u96e2\u958b\u5b50\u6a39\u6642\u6fc0\u6d3b<\/li><\/ul><\/li><li><strong>abort observer == Lower priority<\/strong><ul><li>observer\u70ba\u4f4e\u512a\u5148\u7d1a\u5b50\u6a39<\/li><li>activated: \u7576\u524d\u57f7\u884c\u4fdd\u7559\u5728\u4f4e\u512a\u5148\u7d1a\u5b50\u6a39\u6642\u6fc0\u6d3b<\/li><li>deactivated: \u7576\u524d\u57f7\u884c\u96e2\u958b\u5728\u4f4e\u512a\u5148\u7d1a\u5b50\u6a39\u6642\u6fc0\u6d3b<\/li><\/ul><\/li><li><strong>abort observer == both<\/strong><ul><li>observer\u70ba\u7576\u524d\u5b50\u6a39\u53ca\u4f4e\u512a\u5148\u7d1a\u5b50\u6a39<\/li><li>activated\uff1a\u7576\u524d\u57f7\u884c\u4fdd\u7559\u5728\u5b50\u6a39\u6642\u548c\u5728\u4f4e\u512a\u5148\u7d1a\u5b50\u6a39\u6642\u6fc0\u6d3b\uff08\u5f85\u5be6\u9a57\uff09<\/li><li>deactivated\uff1a\u7576\u524d\u57f7\u884c\u96e2\u958b\u5b50\u6a39\u548c\u4f4e\u512a\u5148\u7d1a\u5b50\u6a39\u6642\u6fc0\u6d3b\uff08\u5f85\u5be6\u9a57\uff09<\/li><\/ul><\/li><\/ul><\/li><li><strong>Receive Tick\uff08AI\uff09<\/strong>\uff1a\u7576Observer\u88ab\u6fc0\u6d3b\u6642\uff0cReceive Observer Activated\u88ab\u8abf\u7528\uff0cReceive Tick\u4e8b\u4ef6\u624d\u958b\u59cb\u6bcf\u5e40\u88ab\u8abf\u7528<\/li><li><strong>Perform Condition Check\uff08AI\uff09<\/strong>\uff1a\u6838\u5fc3\u91cd\u8f09\uff0c\u7528\u4f86\u5bebDecorator\u7684\u5177\u9ad4\u5224\u65b7\u908f\u8f2f<ul><li><p>\u6bcfTick\u548cBlackboardKey\u503c\u6539\u8b8a\u6642\u6703\u88ab\u8abf\u7528<\/p><\/li><\/ul><\/li><\/ul><\/li><\/ul>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-bf1549e elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"bf1549e\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-3fcb195\" data-id=\"3fcb195\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-9e6b346 elementor-widget elementor-widget-code-block-for-elementor\" data-id=\"9e6b346\" data-element_type=\"widget\" data-widget_type=\"code-block-for-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<pre class='line-numbers theme-okaidia' data-show-toolbar='yes'><code class='language-cpp'>\/\/BTDecorator_BlueprintBase.cpp\r\nvoid UBTDecorator_BlueprintBase::TickNode(UBehaviorTreeComponent&amp; OwnerComp, uint8* NodeMemory, float DeltaSeconds)\r\n{\r\n    if (AIOwner != nullptr &amp;&amp; (ReceiveTickImplementations &amp; FBTNodeBPImplementationHelper::AISpecific))\r\n    {\r\n        ReceiveTickAI(AIOwner, AIOwner-&gt;GetPawn(), DeltaSeconds);\r\n    }\r\n    else if (ReceiveTickImplementations &amp; FBTNodeBPImplementationHelper::Generic)\r\n    {\r\n        ReceiveTick(ActorOwner, DeltaSeconds);\r\n    }\r\n        \r\n    \/\/ possible this got ticked due to the decorator being configured as an observer\r\n    if (GetNeedsTickForConditionChecking())\r\n    {\r\n        RequestAbort(OwnerComp, EvaluateAbortType(OwnerComp));\r\n    }\r\n}\r\n\r\nUBTDecorator_BlueprintBase::EAbortType  UBTDecorator_BlueprintBase::EvaluateAbortType(UBehaviorTreeComponent&amp; OwnerComp) const\r\n{\r\n    if (PerformConditionCheckImplementations == 0)\r\n    {\r\n        return EAbortType::Unknown;\r\n    }\r\n\r\n    if (FlowAbortMode == EBTFlowAbortMode::None)\r\n    {\r\n        return EAbortType::NoAbort;\r\n    }\r\n\r\n    const bool bIsOnActiveBranch = OwnerComp.IsExecutingBranch(GetMyNode(), GetChildIndex());\r\n\r\n    EAbortType AbortType = EAbortType::NoAbort;\r\n    if (bIsOnActiveBranch)\r\n    {\r\n        if ((FlowAbortMode == EBTFlowAbortMode::Self || FlowAbortMode == EBTFlowAbortMode::Both) &amp;&amp; CalculateRawConditionValue(OwnerComp, \/*NodeMemory*\/nullptr) == IsInversed())\r\n        {\r\n            AbortType = EAbortType::DeactivateBranch;\r\n        }\r\n    }\r\n    else \r\n    {\r\n        if ((FlowAbortMode == EBTFlowAbortMode::LowerPriority || FlowAbortMode == EBTFlowAbortMode::Both) &amp;&amp; CalculateRawConditionValue(OwnerComp, \/*NodeMemory*\/nullptr) != IsInversed())\r\n        {\r\n            AbortType = EAbortType::ActivateBranch;\r\n        }\r\n    }\r\n\r\n    return AbortType;\r\n}\r\n\r\nbool UBTDecorator_BlueprintBase::CalculateRawConditionValue(UBehaviorTreeComponent&amp; OwnerComp, uint8* NodeMemory) const\r\n{\r\n    bool CurrentCallResult = false;\r\n    if (PerformConditionCheckImplementations != 0)\r\n    {\r\n        \/\/ can't use const functions with blueprints\r\n        UBTDecorator_BlueprintBase* MyNode = (UBTDecorator_BlueprintBase*)this;\r\n\r\n        if (AIOwner != nullptr &amp;&amp; (PerformConditionCheckImplementations &amp; FBTNodeBPImplementationHelper::AISpecific))\r\n        {\r\n            CurrentCallResult = MyNode-&gt;PerformConditionCheckAI(MyNode-&gt;AIOwner, MyNode-&gt;AIOwner-&gt;GetPawn());\r\n        }\r\n        else if (PerformConditionCheckImplementations &amp; FBTNodeBPImplementationHelper::Generic)\r\n        {\r\n            CurrentCallResult = MyNode-&gt;PerformConditionCheck(MyNode-&gt;ActorOwner);\r\n        }\r\n    }\r\n\r\n    return CurrentCallResult;\r\n}\r\n<\/code><\/pre>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-c4b6336 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"c4b6336\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-de8b988\" data-id=\"de8b988\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-156a023 elementor-widget-divider--view-line elementor-widget elementor-widget-divider\" data-id=\"156a023\" data-element_type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"elementor-divider\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-2089e7f elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"2089e7f\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-ab2a393\" data-id=\"ab2a393\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-0be7e73 elementor-widget elementor-widget-text-editor\" data-id=\"0be7e73\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<h4><span style=\"text-decoration: underline;\"><strong>\u6253\u65b7\u8a2d\u7f6e<\/strong><\/span><\/h4><ul><li>\u7576Decorator\u89c0\u5bdf\u7684\u689d\u4ef6\u8b8a\u52d5\u6642\uff0c\u53ef\u4ee5\u6307\u5b9a\u6253\u65b7\u81ea\u5df1\/\u540c\u7d1a\u884c\u70ba\u6a39\u7684\u908f\u8f2f =&gt; Observer aborts<ul><li>None<ul><li>\u4e0d\u6253\u65b7\uff0c\u7b49\u5f85\u672c\u6b21\u57f7\u884c\u7d50\u675f<\/li><\/ul><\/li><li>Self<ul><li>\u4e00\u65e6\u72c0\u614b\u66f4\u6539\u4e14<strong>\u4e0d\u6eff\u8db3<\/strong>Decorator\u689d\u4ef6\uff0c\u7576\u524d\u5b50\u6a39\u5c31\u6703\u7acb\u5373\u4e2d\u6b62<\/li><\/ul><\/li><li>LowerPriority<ul><li>\u4e00\u65e6\u72c0\u614b\u66f4\u6539\u4e14<strong>\u6eff\u8db3<\/strong>Decorator\u689d\u4ef6\uff0c\u4f4e\u512a\u5148\u7d1a\u5b50\u6a39\u5c31\u6703\u7acb\u5373\u4e2d\u6b62\uff0c\u4e26\u57f7\u884c\u8df3\u8f49\u5230Decorator\u6240\u5728\u7bc0\u9ede<\/li><\/ul><\/li><li>Both<ul><li>\u4e00\u65e6\u72c0\u614b\u66f4\u6539\u4e14<strong>\u4e0d\u6eff\u8db3<\/strong>Decorator\u689d\u4ef6\uff0c\u5b50\u6a39\u5c31\u6703\u7acb\u5373\u4e2d\u6b62<\/li><li>\u4e00\u65e6\u72c0\u614b\u66f4\u6539\u4e14<strong>\u6eff\u8db3<\/strong>Decorator\u689d\u4ef6\uff0c\u4f4e\u512a\u5148\u7d1a\u5b50\u6a39\u5c31\u6703\u7acb\u5373\u4e2d\u6b62\uff0c\u4e26\u57f7\u884c\u8df3\u8f49\u5230Decorator\u6240\u5728\u7bc0\u9ede<\/li><\/ul><\/li><\/ul><\/li><\/ul>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-e3df8e7 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"e3df8e7\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-c4c6965\" data-id=\"c4c6965\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-1e40f8d elementor-widget-divider--view-line elementor-widget elementor-widget-divider\" data-id=\"1e40f8d\" data-element_type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"elementor-divider\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>\u672c\u7bc7\u70baUE AI\u7cfb\u5217\u7684\u7b2c\u4e09\u90e8\u5206\uff1a\u884c\u70ba\u6a39Decorator\u985e\u578b\u7bc0\u9ede\u8aaa\u660e<\/p>\n","protected":false},"author":1,"featured_media":4068,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,17],"tags":[],"class_list":["post-4108","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-programming-notes","category-devnotes"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/lonelinerd.com\/wp-content\/uploads\/2024\/03\/FeatureCover_Unreal5ArtificialIntelligence.png","_links":{"self":[{"href":"https:\/\/lonelinerd.com\/index.php\/wp-json\/wp\/v2\/posts\/4108","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lonelinerd.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lonelinerd.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lonelinerd.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lonelinerd.com\/index.php\/wp-json\/wp\/v2\/comments?post=4108"}],"version-history":[{"count":4,"href":"https:\/\/lonelinerd.com\/index.php\/wp-json\/wp\/v2\/posts\/4108\/revisions"}],"predecessor-version":[{"id":4115,"href":"https:\/\/lonelinerd.com\/index.php\/wp-json\/wp\/v2\/posts\/4108\/revisions\/4115"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/lonelinerd.com\/index.php\/wp-json\/wp\/v2\/media\/4068"}],"wp:attachment":[{"href":"https:\/\/lonelinerd.com\/index.php\/wp-json\/wp\/v2\/media?parent=4108"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lonelinerd.com\/index.php\/wp-json\/wp\/v2\/categories?post=4108"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lonelinerd.com\/index.php\/wp-json\/wp\/v2\/tags?post=4108"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}