From d3fe79cf3901c1e449db687ae7b0d83d0a77f478 Mon Sep 17 00:00:00 2001 From: YHH <359807859@qq.com> Date: Fri, 20 Jun 2025 18:21:50 +0800 Subject: [PATCH] example update --- .gitmodules | 3 + .../behavior-tree-examples-guide.bt.json | 2 +- .../cocos-ecs/assets/resources/test.bt.json | 283 +++++ .../assets/resources/test.bt.json.meta | 11 + .../cocos/cocos-ecs/assets/scenes/scene.scene | 1010 +++++++++++++---- .../assets/scripts/ecs/BehaviorTreeExample.ts | 270 +++++ .../scripts/ecs/BehaviorTreeExample.ts.meta | 9 + .../scripts/ecs/BehaviorTreeTestScene.ts | 202 ++++ .../scripts/ecs/BehaviorTreeTestScene.ts.meta | 9 + .../cocos/cocos-ecs/extensions/behaviour-tree | 1 + .../cocos-ecs/extensions/cocos-ecs-extension | 2 +- extensions/cocos/cocos-ecs/package-lock.json | 20 +- extensions/cocos/cocos-ecs/package.json | 6 +- 13 files changed, 1611 insertions(+), 217 deletions(-) create mode 100644 extensions/cocos/cocos-ecs/assets/resources/test.bt.json create mode 100644 extensions/cocos/cocos-ecs/assets/resources/test.bt.json.meta create mode 100644 extensions/cocos/cocos-ecs/assets/scripts/ecs/BehaviorTreeExample.ts create mode 100644 extensions/cocos/cocos-ecs/assets/scripts/ecs/BehaviorTreeExample.ts.meta create mode 100644 extensions/cocos/cocos-ecs/assets/scripts/ecs/BehaviorTreeTestScene.ts create mode 100644 extensions/cocos/cocos-ecs/assets/scripts/ecs/BehaviorTreeTestScene.ts.meta create mode 160000 extensions/cocos/cocos-ecs/extensions/behaviour-tree diff --git a/.gitmodules b/.gitmodules index 7c3919db..451d0c3f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "extensions/cocos/cocos-ecs/extensions/cocos-ecs-extension"] path = extensions/cocos/cocos-ecs/extensions/cocos-ecs-extension url = https://github.com/esengine/cocos-ecs-extension.git +[submodule "extensions/cocos/cocos-ecs/extensions/behaviour-tree"] + path = extensions/cocos/cocos-ecs/extensions/behaviour-tree + url = https://github.com/esengine/behaviour-tree.git diff --git a/extensions/cocos/cocos-ecs/assets/resources/behavior-tree-examples-guide.bt.json b/extensions/cocos/cocos-ecs/assets/resources/behavior-tree-examples-guide.bt.json index 1e02801d..9ce2e53a 100644 --- a/extensions/cocos/cocos-ecs/assets/resources/behavior-tree-examples-guide.bt.json +++ b/extensions/cocos/cocos-ecs/assets/resources/behavior-tree-examples-guide.bt.json @@ -744,7 +744,7 @@ } ], "metadata": { - "name": "behavior-tree-examples-guide.bt", + "name": "behavior-tree-examples-guide", "created": "2025-06-19T04:28:44.589Z", "version": "1.0" }, diff --git a/extensions/cocos/cocos-ecs/assets/resources/test.bt.json b/extensions/cocos/cocos-ecs/assets/resources/test.bt.json new file mode 100644 index 00000000..d9f9c22f --- /dev/null +++ b/extensions/cocos/cocos-ecs/assets/resources/test.bt.json @@ -0,0 +1,283 @@ +{ + "nodes": [ + { + "id": "root_1", + "type": "root", + "name": "行为树指南根", + "children": [ + "selector_main" + ] + }, + { + "id": "selector_main", + "type": "selector", + "name": "主选择器", + "properties": { + "abortType": "LowerPriority" + }, + "children": [ + "repeater_patrol", + "selector_combat", + "sequence_idle" + ] + }, + { + "id": "repeater_patrol", + "type": "repeater", + "name": "巡逻重复器", + "properties": { + "count": -1, + "continueOnFailure": true, + "delayBetween": false + }, + "children": [ + "sequence_patrol" + ] + }, + { + "id": "sequence_patrol", + "type": "sequence", + "name": "巡逻序列", + "properties": { + "abortType": "None" + }, + "children": [ + "decorator_patrol_check", + "action_patrol" + ] + }, + { + "id": "decorator_patrol_check", + "type": "conditional-decorator", + "name": "巡逻条件检查", + "properties": { + "conditionType": "custom", + "executeWhenTrue": true, + "executeWhenFalse": false, + "checkInterval": 1 + }, + "children": [ + "log_patrolling" + ], + "condition": { + "type": "condition-custom", + "properties": { + "conditionCode": { + "name": "条件代码", + "type": "code", + "value": "(context) => {\n // 检查是否处于巡逻状态\n return context.blackboard && context.blackboard.getValue('state') === 'patrol';\n}", + "description": "条件判断函数代码", + "required": true + }, + "conditionName": { + "name": "条件名称", + "type": "string", + "value": "巡逻状态检查", + "description": "用于调试的条件名称", + "required": false + } + } + } + }, + { + "id": "log_patrolling", + "type": "log-action", + "name": "记录巡逻", + "properties": { + "message": "正在执行巡逻任务,当前状态: {{state}}", + "logLevel": "info" + } + }, + { + "id": "action_patrol", + "type": "set-blackboard-value", + "name": "执行巡逻", + "properties": { + "variableName": "lastAction", + "value": "{{state}}_执行中", + "force": false + } + }, + { + "id": "selector_combat", + "type": "selector", + "name": "战斗选择器", + "properties": { + "abortType": "None" + }, + "children": [ + "sequence_attack", + "sequence_defend" + ] + }, + { + "id": "sequence_attack", + "type": "sequence", + "name": "攻击序列", + "properties": { + "abortType": "Self" + }, + "children": [ + "inverter_enemy", + "action_attack" + ] + }, + { + "id": "inverter_enemy", + "type": "inverter", + "name": "敌人检查反转", + "children": [ + "condition_enemy" + ] + }, + { + "id": "condition_enemy", + "type": "condition-random", + "name": "随机敌人出现", + "properties": { + "successProbability": 0.3 + } + }, + { + "id": "action_attack", + "type": "log-action", + "name": "攻击动作", + "properties": { + "message": "发动攻击!生命值: {{health}}, 能量: {{energy}}", + "logLevel": "warn" + } + }, + { + "id": "sequence_defend", + "type": "sequence", + "name": "防御序列", + "properties": { + "abortType": "None" + }, + "children": [ + "wait_defend", + "action_defend" + ] + }, + { + "id": "wait_defend", + "type": "wait-action", + "name": "防御准备", + "properties": { + "waitTime": 0.5, + "useExternalTime": false + } + }, + { + "id": "action_defend", + "type": "execute-action", + "name": "执行防御", + "properties": { + "actionCode": "(context) => {\n // 防御逻辑\n console.log('开始防御姿态');\n if(context.blackboard) {\n context.blackboard.setValue('defendActive', true);\n context.blackboard.setValue('lastAction', '防御中');\n }\n return 'success';\n}", + "actionName": "防御动作_生命值{{health}}" + } + }, + { + "id": "sequence_idle", + "type": "sequence", + "name": "闲置序列", + "properties": { + "abortType": "None" + }, + "children": [ + "action_idle", + "log_status", + "wait_idle" + ] + }, + { + "id": "action_idle", + "type": "set-blackboard-value", + "name": "设置闲置", + "properties": { + "variableName": "state", + "value": "idle", + "force": false + } + }, + { + "id": "log_status", + "type": "log-action", + "name": "状态报告", + "properties": { + "message": "状态报告 - 当前: {{state}}, 上次动作: {{lastAction}}, 防御中: {{defendActive}}", + "logLevel": "debug" + } + }, + { + "id": "wait_idle", + "type": "wait-action", + "name": "闲置等待", + "properties": { + "waitTime": 3, + "useExternalTime": false + } + } + ], + "blackboard": [ + { + "name": "state", + "type": "string", + "value": "patrol", + "description": "当前状态", + "group": "核心状态", + "constraints": { + "allowedValues": [ + "idle", + "patrol", + "combat", + "defend" + ] + } + }, + { + "name": "lastAction", + "type": "string", + "value": "", + "description": "最后执行的动作", + "group": "核心状态" + }, + { + "name": "defendActive", + "type": "boolean", + "value": false, + "description": "是否正在防御", + "group": "战斗状态" + }, + { + "name": "health", + "type": "number", + "value": 100, + "description": "生命值", + "group": "属性", + "constraints": { + "min": 0, + "max": 100, + "step": 1 + } + }, + { + "name": "energy", + "type": "number", + "value": 50, + "description": "能量值", + "group": "属性", + "constraints": { + "min": 0, + "max": 100, + "step": 1 + } + } + ], + "metadata": { + "name": "behavior-tree", + "created": "2025-06-20T07:17:15.437Z", + "version": "1.0", + "exportType": "clean" + } +} \ No newline at end of file diff --git a/extensions/cocos/cocos-ecs/assets/resources/test.bt.json.meta b/extensions/cocos/cocos-ecs/assets/resources/test.bt.json.meta new file mode 100644 index 00000000..73416006 --- /dev/null +++ b/extensions/cocos/cocos-ecs/assets/resources/test.bt.json.meta @@ -0,0 +1,11 @@ +{ + "ver": "2.0.1", + "importer": "json", + "imported": true, + "uuid": "4d7244e6-4be6-46a0-9e38-6915004177e7", + "files": [ + ".json" + ], + "subMetas": {}, + "userData": {} +} diff --git a/extensions/cocos/cocos-ecs/assets/scenes/scene.scene b/extensions/cocos/cocos-ecs/assets/scenes/scene.scene index 98dcd1a3..f041d20f 100644 --- a/extensions/cocos/cocos-ecs/assets/scenes/scene.scene +++ b/extensions/cocos/cocos-ecs/assets/scenes/scene.scene @@ -20,10 +20,13 @@ "__id__": 2 }, { - "__id__": 5 + "__id__": 4 }, { - "__id__": 7 + "__id__": 22 + }, + { + "__id__": 8 } ], "_active": true, @@ -58,197 +61,10 @@ }, "autoReleaseAssets": false, "_globals": { - "__id__": 9 + "__id__": 24 }, "_id": "ff354f0b-c2f5-4dea-8ffb-0152d175d11c" }, - { - "__type__": "cc.Node", - "_name": "Main Light", - "_objFlags": 0, - "__editorExtras__": {}, - "_parent": { - "__id__": 1 - }, - "_children": [], - "_active": true, - "_components": [ - { - "__id__": 3 - } - ], - "_prefab": null, - "_lpos": { - "__type__": "cc.Vec3", - "x": 0, - "y": 0, - "z": 0 - }, - "_lrot": { - "__type__": "cc.Quat", - "x": -0.06397656665577071, - "y": -0.44608233363525845, - "z": -0.8239028751062036, - "w": -0.3436591377065261 - }, - "_lscale": { - "__type__": "cc.Vec3", - "x": 1, - "y": 1, - "z": 1 - }, - "_mobility": 0, - "_layer": 1073741824, - "_euler": { - "__type__": "cc.Vec3", - "x": -117.894, - "y": -194.909, - "z": 38.562 - }, - "_id": "c0y6F5f+pAvI805TdmxIjx" - }, - { - "__type__": "cc.DirectionalLight", - "_name": "", - "_objFlags": 0, - "__editorExtras__": {}, - "node": { - "__id__": 2 - }, - "_enabled": true, - "__prefab": null, - "_color": { - "__type__": "cc.Color", - "r": 255, - "g": 250, - "b": 240, - "a": 255 - }, - "_useColorTemperature": false, - "_colorTemperature": 6550, - "_staticSettings": { - "__id__": 4 - }, - "_visibility": -325058561, - "_illuminanceHDR": 65000, - "_illuminance": 65000, - "_illuminanceLDR": 1.6927083333333335, - "_shadowEnabled": false, - "_shadowPcf": 0, - "_shadowBias": 0.00001, - "_shadowNormalBias": 0, - "_shadowSaturation": 1, - "_shadowDistance": 50, - "_shadowInvisibleOcclusionRange": 200, - "_csmLevel": 4, - "_csmLayerLambda": 0.75, - "_csmOptimizationMode": 2, - "_csmAdvancedOptions": false, - "_csmLayersTransition": false, - "_csmTransitionRange": 0.05, - "_shadowFixedArea": false, - "_shadowNear": 0.1, - "_shadowFar": 10, - "_shadowOrthoSize": 5, - "_id": "597uMYCbhEtJQc0ffJlcgA" - }, - { - "__type__": "cc.StaticLightSettings", - "_baked": false, - "_editorOnly": false, - "_castShadow": false - }, - { - "__type__": "cc.Node", - "_name": "Main Camera", - "_objFlags": 0, - "__editorExtras__": {}, - "_parent": { - "__id__": 1 - }, - "_children": [], - "_active": true, - "_components": [ - { - "__id__": 6 - } - ], - "_prefab": null, - "_lpos": { - "__type__": "cc.Vec3", - "x": -10, - "y": 10, - "z": 10 - }, - "_lrot": { - "__type__": "cc.Quat", - "x": -0.27781593346944056, - "y": -0.36497167621709875, - "z": -0.11507512748638377, - "w": 0.8811195706053617 - }, - "_lscale": { - "__type__": "cc.Vec3", - "x": 1, - "y": 1, - "z": 1 - }, - "_mobility": 0, - "_layer": 1073741824, - "_euler": { - "__type__": "cc.Vec3", - "x": -35, - "y": -45, - "z": 0 - }, - "_id": "c9DMICJLFO5IeO07EPon7U" - }, - { - "__type__": "cc.Camera", - "_name": "", - "_objFlags": 0, - "__editorExtras__": {}, - "node": { - "__id__": 5 - }, - "_enabled": true, - "__prefab": null, - "_projection": 1, - "_priority": 0, - "_fov": 45, - "_fovAxis": 0, - "_orthoHeight": 10, - "_near": 1, - "_far": 1000, - "_color": { - "__type__": "cc.Color", - "r": 51, - "g": 51, - "b": 51, - "a": 255 - }, - "_depth": 1, - "_stencil": 0, - "_clearFlags": 14, - "_rect": { - "__type__": "cc.Rect", - "x": 0, - "y": 0, - "width": 1, - "height": 1 - }, - "_aperture": 19, - "_shutter": 7, - "_iso": 0, - "_screenScale": 1, - "_visibility": 1822425087, - "_targetTexture": null, - "_postProcess": null, - "_usePostProcess": false, - "_cameraType": -1, - "_trackingType": 0, - "_id": "7dWQTpwS5LrIHnc1zAPUtf" - }, { "__type__": "cc.Node", "_name": "ECSManager", @@ -258,10 +74,10 @@ "__id__": 1 }, "_children": [], - "_active": true, + "_active": false, "_components": [ { - "__id__": 8 + "__id__": 3 } ], "_prefab": null, @@ -300,7 +116,7 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 7 + "__id__": 2 }, "_enabled": true, "__prefab": null, @@ -308,30 +124,818 @@ "_id": "40G/Xl9EBLJ7amO+29wrkO" }, { - "__type__": "cc.SceneGlobals", - "ambient": { - "__id__": 10 + "__type__": "cc.Node", + "_name": "BehaviorTreeExample", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": { + "__id__": 1 }, - "shadows": { + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 5 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "a1gA7y2LZAaZqVDOYn5V84" + }, + { + "__type__": "3c3bfSF4atEpIdYZZTtxMV1", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 4 + }, + "_enabled": true, + "__prefab": null, + "statusLabel": { + "__id__": 6 + }, + "logLabel": null, + "startButton": { + "__id__": 17 + }, + "stopButton": null, + "pauseButton": null, + "resumeButton": null, + "_id": "2abWpbFNFJH54Je2kfxJ8H" + }, + { + "__type__": "cc.Label", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 7 + }, + "_enabled": true, + "__prefab": null, + "_customMaterial": null, + "_srcBlendFactor": 2, + "_dstBlendFactor": 4, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_string": "label", + "_horizontalAlign": 1, + "_verticalAlign": 1, + "_actualFontSize": 20, + "_fontSize": 20, + "_fontFamily": "Arial", + "_lineHeight": 40, + "_overflow": 0, + "_enableWrapText": true, + "_font": null, + "_isSystemFontUsed": true, + "_spacingX": 0, + "_isItalic": false, + "_isBold": false, + "_isUnderline": false, + "_underlineHeight": 2, + "_cacheMode": 0, + "_enableOutline": false, + "_outlineColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_outlineWidth": 2, + "_enableShadow": false, + "_shadowColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_shadowOffset": { + "__type__": "cc.Vec2", + "x": 2, + "y": 2 + }, + "_shadowBlur": 2, + "_id": "d39qB9JpBMJZlrJcSOwqU7" + }, + { + "__type__": "cc.Node", + "_name": "Label", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": { + "__id__": 8 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 21 + }, + { + "__id__": 6 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 11.984, + "y": 152.374, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 33554432, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "6fcMVYWRFA1r2GTN2+dzGO" + }, + { + "__type__": "cc.Node", + "_name": "Canvas", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": { + "__id__": 1 + }, + "_children": [ + { + "__id__": 9 + }, + { + "__id__": 11 + }, + { + "__id__": 7 + } + ], + "_active": true, + "_components": [ + { + "__id__": 18 + }, + { + "__id__": 19 + }, + { + "__id__": 20 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 640, + "y": 360, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 33554432, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "3dUZcdj81DZ5yqtsy1h65c" + }, + { + "__type__": "cc.Node", + "_name": "Camera", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": { + "__id__": 8 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 10 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 1000 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 33554432, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "c3bghMkqZOPbmMa3oiZPra" + }, + { + "__type__": "cc.Camera", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 9 + }, + "_enabled": true, + "__prefab": null, + "_projection": 0, + "_priority": 1073741824, + "_fov": 45, + "_fovAxis": 0, + "_orthoHeight": 382.803738317757, + "_near": 1, + "_far": 2000, + "_color": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_depth": 1, + "_stencil": 0, + "_clearFlags": 6, + "_rect": { + "__type__": "cc.Rect", + "x": 0, + "y": 0, + "width": 1, + "height": 1 + }, + "_aperture": 19, + "_shutter": 7, + "_iso": 0, + "_screenScale": 1, + "_visibility": 41943040, + "_targetTexture": null, + "_postProcess": null, + "_usePostProcess": false, + "_cameraType": -1, + "_trackingType": 0, + "_id": "4eW6jmuTxH3qw3bXq7A430" + }, + { + "__type__": "cc.Node", + "_name": "Button", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": { + "__id__": 8 + }, + "_children": [ + { + "__id__": 12 + } + ], + "_active": true, + "_components": [ + { + "__id__": 15 + }, + { + "__id__": 16 + }, + { + "__id__": 17 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 6.097, + "y": -234.248, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 33554432, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "6dKxCdjdpKRKmSyaoQYDaN" + }, + { + "__type__": "cc.Node", + "_name": "Label", + "_objFlags": 512, + "__editorExtras__": {}, + "_parent": { "__id__": 11 }, - "_skybox": { + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 13 + }, + { + "__id__": 14 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 33554432, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "dbb354l4tHTKAyhpdaQ2md" + }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { "__id__": 12 }, + "_enabled": true, + "__prefab": null, + "_contentSize": { + "__type__": "cc.Size", + "width": 100, + "height": 40 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_id": "04VFGWnw5PqoKxYRSyBTUb" + }, + { + "__type__": "cc.Label", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 12 + }, + "_enabled": true, + "__prefab": null, + "_customMaterial": null, + "_srcBlendFactor": 2, + "_dstBlendFactor": 4, + "_color": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_string": "开始", + "_horizontalAlign": 1, + "_verticalAlign": 1, + "_actualFontSize": 20, + "_fontSize": 20, + "_fontFamily": "Arial", + "_lineHeight": 40, + "_overflow": 1, + "_enableWrapText": false, + "_font": null, + "_isSystemFontUsed": true, + "_spacingX": 0, + "_isItalic": false, + "_isBold": false, + "_isUnderline": false, + "_underlineHeight": 2, + "_cacheMode": 0, + "_enableOutline": false, + "_outlineColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_outlineWidth": 2, + "_enableShadow": false, + "_shadowColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_shadowOffset": { + "__type__": "cc.Vec2", + "x": 2, + "y": 2 + }, + "_shadowBlur": 2, + "_id": "b9+onVQMdClZGOSeBsoqNE" + }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 11 + }, + "_enabled": true, + "__prefab": null, + "_contentSize": { + "__type__": "cc.Size", + "width": 100, + "height": 40 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_id": "1d2znr8KxOTYY+p+1fDXS2" + }, + { + "__type__": "cc.Sprite", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 11 + }, + "_enabled": true, + "__prefab": null, + "_customMaterial": null, + "_srcBlendFactor": 2, + "_dstBlendFactor": 4, + "_color": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_spriteFrame": { + "__uuid__": "20835ba4-6145-4fbc-a58a-051ce700aa3e@f9941", + "__expectedType__": "cc.SpriteFrame" + }, + "_type": 1, + "_fillType": 0, + "_sizeMode": 0, + "_fillCenter": { + "__type__": "cc.Vec2", + "x": 0, + "y": 0 + }, + "_fillStart": 0, + "_fillRange": 0, + "_isTrimmedMode": true, + "_useGrayscale": false, + "_atlas": null, + "_id": "d0w3yIfN5J1bFm0kARE00H" + }, + { + "__type__": "cc.Button", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 11 + }, + "_enabled": true, + "__prefab": null, + "clickEvents": [], + "_interactable": true, + "_transition": 2, + "_normalColor": { + "__type__": "cc.Color", + "r": 214, + "g": 214, + "b": 214, + "a": 255 + }, + "_hoverColor": { + "__type__": "cc.Color", + "r": 211, + "g": 211, + "b": 211, + "a": 255 + }, + "_pressedColor": { + "__type__": "cc.Color", + "r": 255, + "g": 255, + "b": 255, + "a": 255 + }, + "_disabledColor": { + "__type__": "cc.Color", + "r": 124, + "g": 124, + "b": 124, + "a": 255 + }, + "_normalSprite": { + "__uuid__": "20835ba4-6145-4fbc-a58a-051ce700aa3e@f9941", + "__expectedType__": "cc.SpriteFrame" + }, + "_hoverSprite": { + "__uuid__": "20835ba4-6145-4fbc-a58a-051ce700aa3e@f9941", + "__expectedType__": "cc.SpriteFrame" + }, + "_pressedSprite": { + "__uuid__": "544e49d6-3f05-4fa8-9a9e-091f98fc2ce8@f9941", + "__expectedType__": "cc.SpriteFrame" + }, + "_disabledSprite": { + "__uuid__": "951249e0-9f16-456d-8b85-a6ca954da16b@f9941", + "__expectedType__": "cc.SpriteFrame" + }, + "_duration": 0.1, + "_zoomScale": 1.2, + "_target": { + "__id__": 11 + }, + "_id": "9dr8T1TidO3Juip5s15Rat" + }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 8 + }, + "_enabled": true, + "__prefab": null, + "_contentSize": { + "__type__": "cc.Size", + "width": 1280, + "height": 720 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_id": "d857MQpyJBFqEtKmMgkPuw" + }, + { + "__type__": "cc.Canvas", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 8 + }, + "_enabled": true, + "__prefab": null, + "_cameraComponent": { + "__id__": 10 + }, + "_alignCanvasWithScreen": true, + "_id": "6d0qbdLTpLKrUDANgtW6UP" + }, + { + "__type__": "cc.Widget", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 8 + }, + "_enabled": true, + "__prefab": null, + "_alignFlags": 45, + "_target": null, + "_left": 0, + "_right": 0, + "_top": 0, + "_bottom": 0, + "_horizontalCenter": 0, + "_verticalCenter": 0, + "_isAbsLeft": true, + "_isAbsRight": true, + "_isAbsTop": true, + "_isAbsBottom": true, + "_isAbsHorizontalCenter": true, + "_isAbsVerticalCenter": true, + "_originalWidth": 0, + "_originalHeight": 0, + "_alignMode": 2, + "_lockFlags": 0, + "_id": "a5pvrwbEtERLlLDLFj6Xzw" + }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 7 + }, + "_enabled": true, + "__prefab": null, + "_contentSize": { + "__type__": "cc.Size", + "width": 42.255859375, + "height": 50.4 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_id": "a5oODrk9xKq5kr4g8/ClUH" + }, + { + "__type__": "cc.Node", + "_name": "BehaviorTreeTestScene", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": { + "__id__": 1 + }, + "_children": [], + "_active": true, + "_components": [ + { + "__id__": 23 + } + ], + "_prefab": null, + "_lpos": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 1, + "y": 1, + "z": 1 + }, + "_mobility": 0, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "b3lpbBD/ZKEZ+1cwfr70lF" + }, + { + "__type__": "0c14b5B3x1L3Ij9suUE7N7m", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 22 + }, + "_enabled": true, + "__prefab": null, + "_id": "11PmHjJBZKobQQa5dpzlJV" + }, + { + "__type__": "cc.SceneGlobals", + "ambient": { + "__id__": 25 + }, + "shadows": { + "__id__": 26 + }, + "_skybox": { + "__id__": 27 + }, "fog": { - "__id__": 13 + "__id__": 28 }, "octree": { - "__id__": 14 + "__id__": 29 }, "skin": { - "__id__": 15 + "__id__": 30 }, "lightProbeInfo": { - "__id__": 16 + "__id__": 31 }, "postSettings": { - "__id__": 17 + "__id__": 32 }, "bakedWithStationaryMainLight": false, "bakedWithHighpLightmap": false diff --git a/extensions/cocos/cocos-ecs/assets/scripts/ecs/BehaviorTreeExample.ts b/extensions/cocos/cocos-ecs/assets/scripts/ecs/BehaviorTreeExample.ts new file mode 100644 index 00000000..e875b65e --- /dev/null +++ b/extensions/cocos/cocos-ecs/assets/scripts/ecs/BehaviorTreeExample.ts @@ -0,0 +1,270 @@ +import { _decorator, Component, Node, Label, Button, resources, JsonAsset } from 'cc'; +import { + BehaviorTreeBuilder, + BehaviorTree, + Blackboard, + BehaviorTreeJSONConfig +} from '@esengine/ai'; + +const { ccclass, property } = _decorator; + +/** + * 行为树测试示例 + * 使用 @esengine/ai 包的 BehaviorTreeBuilder API 自动加载和初始化行为树 + * + * 特性: + * - 自动从JSON配置文件加载行为树 + * - 自动初始化黑板变量 + * - 支持行为树的启动、停止、暂停、恢复 + * - 实时显示黑板变量状态 + */ +@ccclass('BehaviorTreeExample') +export class BehaviorTreeExample extends Component { + + @property(Label) + statusLabel: Label = null; + + @property(Label) + logLabel: Label = null; + + @property(Button) + startButton: Button = null; + + @property(Button) + stopButton: Button = null; + + @property(Button) + pauseButton: Button = null; + + @property(Button) + resumeButton: Button = null; + + private behaviorTree: BehaviorTree = null; + private blackboard: Blackboard = null; + private isRunning: boolean = false; + private isPaused: boolean = false; + private logs: string[] = []; + private executionContext: any = null; + private updateTimer: number = 0; + + onLoad() { + this.setupUI(); + this.loadBehaviorTree(); + } + + private setupUI() { + if (this.startButton) { + this.startButton.node.on('click', this.startBehaviorTree, this); + } + if (this.stopButton) { + this.stopButton.node.on('click', this.stopBehaviorTree, this); + } + if (this.pauseButton) { + this.pauseButton.node.on('click', this.pauseBehaviorTree, this); + } + if (this.resumeButton) { + this.resumeButton.node.on('click', this.resumeBehaviorTree, this); + } + + this.updateStatus('初始化中...'); + this.updateLog('行为树测试组件已加载'); + } + + private async loadBehaviorTree() { + try { + this.updateStatus('加载行为树配置...'); + + // 从resources目录加载test.bt.json文件 + resources.load('test.bt', JsonAsset, (err, jsonAsset: JsonAsset) => { + if (err) { + console.error('加载行为树配置失败:', err); + this.updateStatus('加载失败: ' + err.message); + this.updateLog('❌ 加载test.bt.json失败: ' + err.message); + return; + } + + try { + const config = jsonAsset.json as BehaviorTreeJSONConfig; + this.setupBehaviorTree(config); + } catch (error) { + console.error('解析行为树配置失败:', error); + this.updateStatus('解析失败: ' + error.message); + this.updateLog('❌ 解析行为树配置失败: ' + error.message); + } + }); + + } catch (error) { + console.error('行为树加载过程出错:', error); + this.updateStatus('加载出错: ' + error.message); + this.updateLog('❌ 行为树加载过程出错: ' + error.message); + } + } + + private setupBehaviorTree(config: BehaviorTreeJSONConfig) { + try { + // 创建执行上下文 + this.executionContext = { + node: this.node, + component: this, + // 添加日志方法供行为树节点使用 + log: (message: string, level: string = 'info') => { + this.updateLog(`🤖 [${level.toUpperCase()}] ${message}`); + } + }; + + // 🎯 使用 @esengine/ai 的 BehaviorTreeBuilder API - 一行代码完成所有初始化! + const result = BehaviorTreeBuilder.fromBehaviorTreeConfig(config, this.executionContext); + + this.behaviorTree = result.tree; + this.blackboard = result.blackboard; + this.executionContext = result.context; + + this.updateStatus('行为树加载完成,准备执行'); + this.updateLog('✅ 行为树创建成功(使用 @esengine/ai 包)'); + this.updateLog(`📊 节点总数: ${config.nodes ? config.nodes.length : 0}`); + this.updateLog(`📋 变量总数: ${config.blackboard ? config.blackboard.length : 0}`); + + // 显示黑板变量初始状态 + this.logBlackboardStatus(); + + // 启用开始按钮 + if (this.startButton) { + this.startButton.interactable = true; + } + + } catch (error) { + console.error('设置行为树失败:', error); + this.updateStatus('设置失败: ' + error.message); + this.updateLog('❌ 行为树设置失败: ' + error.message); + } + } + + private startBehaviorTree() { + if (!this.behaviorTree) { + this.updateLog('❌ 行为树未准备好'); + return; + } + + this.isRunning = true; + this.isPaused = false; + // 重置行为树状态 + this.behaviorTree.reset(); + this.updateStatus('执行中...'); + this.updateLog('🚀 开始执行行为树(自动初始化黑板)'); + + // 更新按钮状态 + if (this.startButton) this.startButton.interactable = false; + if (this.stopButton) this.stopButton.interactable = true; + if (this.pauseButton) this.pauseButton.interactable = true; + if (this.resumeButton) this.resumeButton.interactable = false; + } + + private stopBehaviorTree() { + this.isRunning = false; + this.isPaused = false; + this.updateStatus('已停止'); + this.updateLog('⏹️ 行为树执行已停止'); + + // 重置行为树状态 + if (this.behaviorTree) { + this.behaviorTree.reset(); + } + + // 更新按钮状态 + if (this.startButton) this.startButton.interactable = true; + if (this.stopButton) this.stopButton.interactable = false; + if (this.pauseButton) this.pauseButton.interactable = false; + if (this.resumeButton) this.resumeButton.interactable = false; + } + + private pauseBehaviorTree() { + this.isPaused = true; + this.updateStatus('已暂停'); + this.updateLog('⏸️ 行为树执行已暂停'); + + // 更新按钮状态 + if (this.pauseButton) this.pauseButton.interactable = false; + if (this.resumeButton) this.resumeButton.interactable = true; + } + + private resumeBehaviorTree() { + this.isPaused = false; + this.updateStatus('执行中...'); + this.updateLog('▶️ 行为树执行已恢复'); + + // 更新按钮状态 + if (this.pauseButton) this.pauseButton.interactable = true; + if (this.resumeButton) this.resumeButton.interactable = false; + } + + update(deltaTime: number) { + if (!this.isRunning || this.isPaused || !this.behaviorTree) { + return; + } + + this.updateTimer += deltaTime; + + // 每帧执行行为树 + try { + this.behaviorTree.tick(deltaTime); + + // 每2秒输出一次状态信息 + if (this.updateTimer >= 2.0) { + this.updateTimer = 0; + this.logBlackboardStatus(); + + // 检查行为树是否处于活动状态 + const isActive = this.behaviorTree.isActive(); + if (!isActive) { + this.updateLog('✅ 行为树执行完成'); + // 注意:这里只是演示,实际上行为树会持续运行 + // 如果需要检查完成状态,需要通过黑板变量或其他逻辑判断 + } + } + + } catch (error) { + console.error('行为树执行出错:', error); + this.updateLog('❌ 执行出错: ' + error.message); + this.stopBehaviorTree(); + } + } + + private logBlackboardStatus() { + if (!this.blackboard) return; + + // 获取所有黑板变量的当前值 + const variables = ['state', 'lastAction', 'defendActive', 'health', 'energy']; + const status = variables.map(name => { + const value = this.blackboard.getValue(name, 'undefined'); + return `${name}:${value}`; + }).join(', '); + + this.updateLog(`📊 状态: ${status}`); + } + + private updateStatus(status: string) { + if (this.statusLabel) { + this.statusLabel.string = status; + } + console.log('[BehaviorTree] 状态:', status); + } + + private updateLog(message: string) { + this.logs.push(`[${new Date().toLocaleTimeString()}] ${message}`); + + // 只保留最新的25条日志 + if (this.logs.length > 25) { + this.logs.shift(); + } + + if (this.logLabel) { + this.logLabel.string = this.logs.join('\n'); + } + + console.log('[BehaviorTree]', message); + } + + onDestroy() { + this.stopBehaviorTree(); + } +} \ No newline at end of file diff --git a/extensions/cocos/cocos-ecs/assets/scripts/ecs/BehaviorTreeExample.ts.meta b/extensions/cocos/cocos-ecs/assets/scripts/ecs/BehaviorTreeExample.ts.meta new file mode 100644 index 00000000..cc0bb610 --- /dev/null +++ b/extensions/cocos/cocos-ecs/assets/scripts/ecs/BehaviorTreeExample.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "4.0.24", + "importer": "typescript", + "imported": true, + "uuid": "3c3bf485-e1ab-44a4-8758-6594edc4c575", + "files": [], + "subMetas": {}, + "userData": {} +} diff --git a/extensions/cocos/cocos-ecs/assets/scripts/ecs/BehaviorTreeTestScene.ts b/extensions/cocos/cocos-ecs/assets/scripts/ecs/BehaviorTreeTestScene.ts new file mode 100644 index 00000000..d94223dd --- /dev/null +++ b/extensions/cocos/cocos-ecs/assets/scripts/ecs/BehaviorTreeTestScene.ts @@ -0,0 +1,202 @@ +import { _decorator, Component, Node, Label, Button, Canvas, UITransform, Widget, Layout, Sprite, Color } from 'cc'; +import { BehaviorTreeExample } from './BehaviorTreeExample'; + +const { ccclass, property } = _decorator; + +/** + * 行为树测试场景 + * 自动创建UI界面用于测试行为树 + */ +@ccclass('BehaviorTreeTestScene') +export class BehaviorTreeTestScene extends Component { + + onLoad() { + this.createTestUI(); + } + + private createTestUI() { + // 创建Canvas + const canvasNode = new Node('BehaviorTreeTestCanvas'); + canvasNode.addComponent(Canvas); + canvasNode.addComponent(UITransform); + canvasNode.parent = this.node; + + // 创建背景 + const backgroundNode = new Node('Background'); + const backgroundTransform = backgroundNode.addComponent(UITransform); + backgroundTransform.setContentSize(1920, 1080); + const backgroundSprite = backgroundNode.addComponent(Sprite); + backgroundSprite.color = new Color(40, 40, 40, 255); + backgroundNode.parent = canvasNode; + + // 设置Widget组件使背景充满整个画布 + const backgroundWidget = backgroundNode.addComponent(Widget); + backgroundWidget.isAlignTop = true; + backgroundWidget.isAlignBottom = true; + backgroundWidget.isAlignLeft = true; + backgroundWidget.isAlignRight = true; + + // 创建主容器 + const mainContainer = new Node('MainContainer'); + const mainTransform = mainContainer.addComponent(UITransform); + mainTransform.setContentSize(1600, 900); + mainContainer.parent = canvasNode; + + // 设置主容器居中 + const mainWidget = mainContainer.addComponent(Widget); + mainWidget.isAlignHorizontalCenter = true; + mainWidget.isAlignVerticalCenter = true; + + // 设置主容器的Layout + const mainLayout = mainContainer.addComponent(Layout); + mainLayout.type = Layout.Type.VERTICAL; + mainLayout.spacingY = 20; + mainLayout.paddingTop = 50; + mainLayout.paddingBottom = 50; + mainLayout.paddingLeft = 50; + mainLayout.paddingRight = 50; + + // 创建标题 + const titleNode = this.createText('简化API行为树测试器', 48, Color.WHITE); + titleNode.parent = mainContainer; + + // 创建状态显示区域 + const statusContainer = new Node('StatusContainer'); + const statusTransform = statusContainer.addComponent(UITransform); + statusTransform.setContentSize(1500, 80); + statusContainer.parent = mainContainer; + + const statusLayout = statusContainer.addComponent(Layout); + statusLayout.type = Layout.Type.HORIZONTAL; + statusLayout.spacingX = 20; + + // 状态标签 + const statusLabelNode = this.createText('状态: 初始化中...', 24, Color.YELLOW); + statusLabelNode.parent = statusContainer; + + // 创建控制按钮区域 + const buttonContainer = new Node('ButtonContainer'); + const buttonTransform = buttonContainer.addComponent(UITransform); + buttonTransform.setContentSize(1500, 80); + buttonContainer.parent = mainContainer; + + const buttonLayout = buttonContainer.addComponent(Layout); + buttonLayout.type = Layout.Type.HORIZONTAL; + buttonLayout.spacingX = 20; + + // 创建控制按钮 + const startButton = this.createButton('开始执行', Color.GREEN); + const stopButton = this.createButton('停止', Color.RED); + const pauseButton = this.createButton('暂停', Color.YELLOW); + const resumeButton = this.createButton('恢复', Color.BLUE); + + startButton.parent = buttonContainer; + stopButton.parent = buttonContainer; + pauseButton.parent = buttonContainer; + resumeButton.parent = buttonContainer; + + // 创建说明区域 + const infoContainer = new Node('InfoContainer'); + const infoTransform = infoContainer.addComponent(UITransform); + infoTransform.setContentSize(1500, 60); + infoContainer.parent = mainContainer; + + const infoNode = this.createText('使用新的简化API - 一行代码完成所有初始化!', 18, Color.CYAN); + infoNode.parent = infoContainer; + + // 创建日志显示区域 + const logContainer = new Node('LogContainer'); + const logTransform = logContainer.addComponent(UITransform); + logTransform.setContentSize(1500, 600); + logContainer.parent = mainContainer; + + // 日志背景 + const logBackground = new Node('LogBackground'); + const logBgTransform = logBackground.addComponent(UITransform); + logBgTransform.setContentSize(1500, 600); + const logBgSprite = logBackground.addComponent(Sprite); + logBgSprite.color = new Color(20, 20, 20, 255); + logBackground.parent = logContainer; + + // 日志文本 + const logLabelNode = this.createText('等待行为树配置加载...', 16, Color.CYAN); + const logLabel = logLabelNode.getComponent(Label); + logLabel.overflow = Label.Overflow.RESIZE_HEIGHT; + logLabel.verticalAlign = Label.VerticalAlign.TOP; + logLabel.horizontalAlign = Label.HorizontalAlign.LEFT; + const logTransformComp = logLabelNode.getComponent(UITransform); + logTransformComp.setContentSize(1450, 550); + logLabelNode.parent = logContainer; + + // 设置日志文本位置 + const logWidget = logLabelNode.addComponent(Widget); + logWidget.isAlignTop = true; + logWidget.isAlignLeft = true; + logWidget.top = 25; + logWidget.left = 25; + + // 添加BehaviorTreeExample组件 + const behaviorTreeExample = this.node.addComponent(BehaviorTreeExample); + behaviorTreeExample.statusLabel = statusLabelNode.getComponent(Label); + behaviorTreeExample.logLabel = logLabel; + behaviorTreeExample.startButton = startButton.getComponent(Button); + behaviorTreeExample.stopButton = stopButton.getComponent(Button); + behaviorTreeExample.pauseButton = pauseButton.getComponent(Button); + behaviorTreeExample.resumeButton = resumeButton.getComponent(Button); + + // 初始化按钮状态 + stopButton.getComponent(Button).interactable = false; + pauseButton.getComponent(Button).interactable = false; + resumeButton.getComponent(Button).interactable = false; + startButton.getComponent(Button).interactable = false; // 等待行为树配置加载完成 + + console.log('行为树测试UI创建完成'); + } + + private createText(text: string, fontSize: number, color: Color): Node { + const textNode = new Node('Text'); + const textTransform = textNode.addComponent(UITransform); + + const label = textNode.addComponent(Label); + label.string = text; + label.fontSize = fontSize; + label.color = color; + label.lineHeight = fontSize + 4; + + // 根据文本内容调整大小 + const estimatedWidth = Math.max(200, text.length * fontSize * 0.6); + textTransform.setContentSize(estimatedWidth, fontSize + 10); + + return textNode; + } + + private createButton(text: string, color: Color): Node { + const buttonNode = new Node('Button'); + const buttonTransform = buttonNode.addComponent(UITransform); + buttonTransform.setContentSize(180, 60); + + // 按钮背景 + const buttonSprite = buttonNode.addComponent(Sprite); + buttonSprite.color = color; + + // 按钮组件 + const button = buttonNode.addComponent(Button); + button.target = buttonNode; + + // 按钮文本 + const labelNode = new Node('Label'); + const labelTransform = labelNode.addComponent(UITransform); + labelTransform.setContentSize(170, 50); + + const label = labelNode.addComponent(Label); + label.string = text; + label.fontSize = 20; + label.color = Color.WHITE; + label.horizontalAlign = Label.HorizontalAlign.CENTER; + label.verticalAlign = Label.VerticalAlign.CENTER; + + labelNode.parent = buttonNode; + + return buttonNode; + } +} \ No newline at end of file diff --git a/extensions/cocos/cocos-ecs/assets/scripts/ecs/BehaviorTreeTestScene.ts.meta b/extensions/cocos/cocos-ecs/assets/scripts/ecs/BehaviorTreeTestScene.ts.meta new file mode 100644 index 00000000..5bb5a1a1 --- /dev/null +++ b/extensions/cocos/cocos-ecs/assets/scripts/ecs/BehaviorTreeTestScene.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "4.0.24", + "importer": "typescript", + "imported": true, + "uuid": "0c14be41-df1d-4bdc-88fd-b2e504ecdee6", + "files": [], + "subMetas": {}, + "userData": {} +} diff --git a/extensions/cocos/cocos-ecs/extensions/behaviour-tree b/extensions/cocos/cocos-ecs/extensions/behaviour-tree new file mode 160000 index 00000000..25598129 --- /dev/null +++ b/extensions/cocos/cocos-ecs/extensions/behaviour-tree @@ -0,0 +1 @@ +Subproject commit 25598129b2cf463cf573b39503bff7bac44a99b1 diff --git a/extensions/cocos/cocos-ecs/extensions/cocos-ecs-extension b/extensions/cocos/cocos-ecs/extensions/cocos-ecs-extension index 54233b97..b6a2ee1e 160000 --- a/extensions/cocos/cocos-ecs/extensions/cocos-ecs-extension +++ b/extensions/cocos/cocos-ecs/extensions/cocos-ecs-extension @@ -1 +1 @@ -Subproject commit 54233b97733987d488b14342ed8a558fa1faa6f8 +Subproject commit b6a2ee1e2e2692c96c0c884ed69d67e9c13ea6d8 diff --git a/extensions/cocos/cocos-ecs/package-lock.json b/extensions/cocos/cocos-ecs/package-lock.json index d5ce273a..6f3128f2 100644 --- a/extensions/cocos/cocos-ecs/package-lock.json +++ b/extensions/cocos/cocos-ecs/package-lock.json @@ -6,23 +6,25 @@ "": { "name": "cocos-ecs", "dependencies": { - "@esengine/ai": "^2.0.1", - "@esengine/ecs-framework": "^2.1.19" + "@esengine/ai": "^2.0.6", + "@esengine/ecs-framework": "^2.1.22" } }, "node_modules/@esengine/ai": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@esengine/ai/-/ai-2.0.1.tgz", - "integrity": "sha512-qGGYc4kYlSJzCkBDJa+p5OruOnDvnL2oJ/ciKSHsPJVdn1tIefPEkUofJyMVGo4my5ubGr2ky6igTLtLYmhzRg==", - "license": "MIT", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@esengine/ai/-/ai-2.0.6.tgz", + "integrity": "sha512-IPP9jh6GL6MG5Hh5gL1OnkfC1J2Eu1V2KXYCov3kMj/4gUdmehm3Ga0sPSlyctBUwQkYVFr3A7G0QUY+Ts4y6Q==", + "dependencies": { + "@esengine/ecs-framework": "^2.1.20" + }, "engines": { "node": ">=16.0.0" } }, "node_modules/@esengine/ecs-framework": { - "version": "2.1.20", - "resolved": "https://registry.npmjs.org/@esengine/ecs-framework/-/ecs-framework-2.1.20.tgz", - "integrity": "sha512-L6PJ1uoXIttzjYt66shZPdmJ4lU38SyqRnEcVJexcR+V6iyQ/U7H8yjvQjeTIlBb0u7JDBEC6a8B4Cr6VlsF9Q==", + "version": "2.1.22", + "resolved": "https://registry.npmjs.org/@esengine/ecs-framework/-/ecs-framework-2.1.22.tgz", + "integrity": "sha512-U5zQJJC7eQeiIUMV1Y784rOJoVK9x8ZLDI65+8Bbt3PcBWzn+qspLe4FBlJU4XBZcMbmEo5vJltvRNkN7iVPZA==", "engines": { "node": ">=16.0.0" } diff --git a/extensions/cocos/cocos-ecs/package.json b/extensions/cocos/cocos-ecs/package.json index c35b2052..a48daa2a 100644 --- a/extensions/cocos/cocos-ecs/package.json +++ b/extensions/cocos/cocos-ecs/package.json @@ -5,7 +5,7 @@ "version": "3.8.6" }, "dependencies": { - "@esengine/ai": "^2.0.1", - "@esengine/ecs-framework": "^2.1.19" + "@esengine/ecs-framework": "^2.1.22", + "@esengine/ai": "^2.0.6" } -} +} \ No newline at end of file