移除测试代码
This commit is contained in:
@@ -1,293 +0,0 @@
|
||||
import { _decorator, Component, Node, Label } from 'cc';
|
||||
import {
|
||||
BehaviorTreeBuilder,
|
||||
BehaviorTree,
|
||||
Blackboard
|
||||
} from '@esengine/ai';
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
/**
|
||||
* 行为树示例用法
|
||||
* 展示如何在Cocos Creator中加载并执行行为树
|
||||
*/
|
||||
@ccclass('BehaviorTreeExampleUsage')
|
||||
export class BehaviorTreeExampleUsage extends Component {
|
||||
|
||||
@property(Label)
|
||||
statusLabel: Label = null;
|
||||
|
||||
@property(Label)
|
||||
logLabel: Label = null;
|
||||
|
||||
private behaviorTree: BehaviorTree<any> = null;
|
||||
private blackboard: Blackboard = null;
|
||||
private isRunning: boolean = false;
|
||||
private logs: string[] = [];
|
||||
private executionContext: any = null;
|
||||
|
||||
onLoad() {
|
||||
this.setupBehaviorTree();
|
||||
}
|
||||
|
||||
private setupBehaviorTree() {
|
||||
try {
|
||||
// 行为树配置(通常从JSON文件加载)
|
||||
const behaviorTreeConfig = {
|
||||
"nodes": [
|
||||
{
|
||||
"id": "root_1",
|
||||
"type": "root",
|
||||
"name": "AI智能体行为树",
|
||||
"children": ["selector_main"]
|
||||
},
|
||||
{
|
||||
"id": "selector_main",
|
||||
"type": "selector",
|
||||
"name": "主选择器",
|
||||
"properties": {
|
||||
"abortType": "LowerPriority"
|
||||
},
|
||||
"children": ["sequence_combat", "sequence_patrol", "sequence_idle"]
|
||||
},
|
||||
{
|
||||
"id": "sequence_combat",
|
||||
"type": "sequence",
|
||||
"name": "战斗序列",
|
||||
"children": ["condition_enemy", "action_attack"]
|
||||
},
|
||||
{
|
||||
"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_patrol",
|
||||
"type": "sequence",
|
||||
"name": "巡逻序列",
|
||||
"children": ["action_move", "wait_patrol"]
|
||||
},
|
||||
{
|
||||
"id": "action_move",
|
||||
"type": "set-blackboard-value",
|
||||
"name": "移动巡逻",
|
||||
"properties": {
|
||||
"variableName": "lastAction",
|
||||
"value": "巡逻中"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "wait_patrol",
|
||||
"type": "wait-action",
|
||||
"name": "巡逻等待",
|
||||
"properties": {
|
||||
"waitTime": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "sequence_idle",
|
||||
"type": "sequence",
|
||||
"name": "闲置序列",
|
||||
"children": ["action_idle", "wait_idle"]
|
||||
},
|
||||
{
|
||||
"id": "action_idle",
|
||||
"type": "log-action",
|
||||
"name": "闲置状态",
|
||||
"properties": {
|
||||
"message": "当前状态: 闲置中,生命值: {{health}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "wait_idle",
|
||||
"type": "wait-action",
|
||||
"name": "闲置等待",
|
||||
"properties": {
|
||||
"waitTime": 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"blackboard": [
|
||||
{
|
||||
"name": "health",
|
||||
"type": "number",
|
||||
"value": 100,
|
||||
"description": "角色生命值"
|
||||
},
|
||||
{
|
||||
"name": "energy",
|
||||
"type": "number",
|
||||
"value": 80,
|
||||
"description": "角色能量值"
|
||||
},
|
||||
{
|
||||
"name": "lastAction",
|
||||
"type": "string",
|
||||
"value": "待机",
|
||||
"description": "最后执行的动作"
|
||||
},
|
||||
{
|
||||
"name": "enemyDetected",
|
||||
"type": "boolean",
|
||||
"value": false,
|
||||
"description": "是否检测到敌人"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// 创建执行上下文
|
||||
this.executionContext = {
|
||||
node: this.node,
|
||||
component: this,
|
||||
// 添加日志方法供行为树节点使用
|
||||
log: (message: string, level: string = 'info') => {
|
||||
this.addLog(`🤖 [${level.toUpperCase()}] ${message}`);
|
||||
}
|
||||
};
|
||||
|
||||
// 🎯 使用 @esengine/ai 的 BehaviorTreeBuilder API - 一行代码完成所有初始化!
|
||||
const result = BehaviorTreeBuilder.fromBehaviorTreeConfig(behaviorTreeConfig, this.executionContext);
|
||||
|
||||
this.behaviorTree = result.tree;
|
||||
this.blackboard = result.blackboard;
|
||||
this.executionContext = result.context;
|
||||
|
||||
this.updateStatus('行为树加载完成');
|
||||
this.addLog('✅ 行为树初始化成功');
|
||||
this.addLog(`📊 节点总数: ${behaviorTreeConfig.nodes.length}`);
|
||||
this.addLog(`📋 变量总数: ${behaviorTreeConfig.blackboard.length}`);
|
||||
|
||||
// 自动开始执行
|
||||
this.startBehaviorTree();
|
||||
|
||||
} catch (error) {
|
||||
console.error('行为树设置失败:', error);
|
||||
this.updateStatus('设置失败: ' + error.message);
|
||||
this.addLog('❌ 行为树设置失败: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
private startBehaviorTree() {
|
||||
this.isRunning = true;
|
||||
this.behaviorTree.reset();
|
||||
this.updateStatus('执行中...');
|
||||
this.addLog('🚀 开始执行行为树');
|
||||
}
|
||||
|
||||
private stopBehaviorTree() {
|
||||
this.isRunning = false;
|
||||
this.updateStatus('已停止');
|
||||
this.addLog('⏹️ 行为树执行已停止');
|
||||
|
||||
if (this.behaviorTree) {
|
||||
this.behaviorTree.reset();
|
||||
}
|
||||
}
|
||||
|
||||
update(deltaTime: number) {
|
||||
if (!this.isRunning || !this.behaviorTree) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 每帧执行行为树
|
||||
this.behaviorTree.tick(deltaTime);
|
||||
|
||||
} catch (error) {
|
||||
console.error('行为树执行出错:', error);
|
||||
this.addLog('❌ 执行出错: ' + error.message);
|
||||
this.stopBehaviorTree();
|
||||
}
|
||||
}
|
||||
|
||||
private updateStatus(status: string) {
|
||||
if (this.statusLabel) {
|
||||
this.statusLabel.string = status;
|
||||
}
|
||||
console.log('[BehaviorTree] 状态:', status);
|
||||
}
|
||||
|
||||
private addLog(message: string) {
|
||||
this.logs.push(`[${new Date().toLocaleTimeString()}] ${message}`);
|
||||
|
||||
// 只保留最新的20条日志
|
||||
if (this.logs.length > 20) {
|
||||
this.logs.shift();
|
||||
}
|
||||
|
||||
if (this.logLabel) {
|
||||
this.logLabel.string = this.logs.join('\n');
|
||||
}
|
||||
|
||||
console.log('[BehaviorTree]', message);
|
||||
}
|
||||
|
||||
// 手动控制方法(可以绑定到UI按钮)
|
||||
onStartButtonClick() {
|
||||
if (!this.isRunning) {
|
||||
this.startBehaviorTree();
|
||||
}
|
||||
}
|
||||
|
||||
onStopButtonClick() {
|
||||
if (this.isRunning) {
|
||||
this.stopBehaviorTree();
|
||||
}
|
||||
}
|
||||
|
||||
// 修改黑板变量的示例方法
|
||||
onModifyHealthClick() {
|
||||
if (this.blackboard) {
|
||||
const currentHealth = this.blackboard.getValue('health', 100);
|
||||
const newHealth = Math.max(0, currentHealth - 10);
|
||||
this.blackboard.setValue('health', newHealth);
|
||||
this.addLog(`🩺 生命值变更: ${currentHealth} -> ${newHealth}`);
|
||||
}
|
||||
}
|
||||
|
||||
onModifyEnergyClick() {
|
||||
if (this.blackboard) {
|
||||
const currentEnergy = this.blackboard.getValue('energy', 80);
|
||||
const newEnergy = Math.max(0, currentEnergy - 5);
|
||||
this.blackboard.setValue('energy', newEnergy);
|
||||
this.addLog(`⚡ 能量变更: ${currentEnergy} -> ${newEnergy}`);
|
||||
}
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
this.stopBehaviorTree();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用说明:
|
||||
*
|
||||
* 1. 安装依赖:
|
||||
* npm install @esengine/ai
|
||||
*
|
||||
* 2. 将此脚本挂载到场景中的节点上
|
||||
*
|
||||
* 3. 在属性检查器中设置:
|
||||
* - statusLabel: 用于显示当前状态的Label组件
|
||||
* - logLabel: 用于显示日志信息的Label组件
|
||||
*
|
||||
* 4. 运行场景,观察行为树的执行效果
|
||||
*
|
||||
* 5. 可以添加按钮并绑定控制方法:
|
||||
* - onStartButtonClick(): 开始执行
|
||||
* - onStopButtonClick(): 停止执行
|
||||
* - onModifyHealthClick(): 修改生命值
|
||||
* - onModifyEnergyClick(): 修改能量值
|
||||
*/
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "9013db83-08a6-4613-8911-016bfdd65239",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -1,314 +0,0 @@
|
||||
import { _decorator, Component, Node, Label, Button } from 'cc';
|
||||
import {
|
||||
BehaviorTreeBuilder,
|
||||
BehaviorTree,
|
||||
Blackboard,
|
||||
BehaviorTreeJSONConfig
|
||||
} from '@esengine/ai';
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
/**
|
||||
* 完整行为树指南使用示例
|
||||
*
|
||||
* 此示例展示了高级行为树特性:
|
||||
* 1. 条件装饰器 (Conditional Decorator)
|
||||
* 2. 重复器 (Repeater)
|
||||
* 3. 反转器 (Inverter)
|
||||
* 4. 黑板变量引用 {{variable}}
|
||||
* 5. 复杂的组合行为逻辑
|
||||
* 6. 自定义条件和动作
|
||||
*
|
||||
* 包含三种行为模式:
|
||||
* - 巡逻模式:重复执行巡逻序列
|
||||
* - 战斗模式:检测敌人并攻击/防御
|
||||
* - 闲置模式:状态报告和等待
|
||||
*/
|
||||
@ccclass('BehaviorTreeGuideUsage')
|
||||
export class BehaviorTreeGuideUsage extends Component {
|
||||
|
||||
@property(Label)
|
||||
statusLabel: Label = null;
|
||||
|
||||
@property(Label)
|
||||
logLabel: Label = null;
|
||||
|
||||
@property(Button)
|
||||
controlButton: Button = null;
|
||||
|
||||
@property(Button)
|
||||
switchStateButton: Button = null;
|
||||
|
||||
private behaviorTree: BehaviorTree<any> = null;
|
||||
private blackboard: Blackboard = null;
|
||||
private isRunning: boolean = false;
|
||||
private logs: string[] = [];
|
||||
private currentStateIndex: number = 0;
|
||||
private states = ['patrol', 'combat', 'idle'];
|
||||
|
||||
onLoad() {
|
||||
this.setupUI();
|
||||
this.initializeBehaviorTree();
|
||||
}
|
||||
|
||||
private setupUI() {
|
||||
if (this.controlButton) {
|
||||
this.controlButton.node.on('click', this.toggleExecution, this);
|
||||
}
|
||||
if (this.switchStateButton) {
|
||||
this.switchStateButton.node.on('click', this.switchState, this);
|
||||
}
|
||||
|
||||
this.updateStatus('初始化完整行为树指南...');
|
||||
this.addLog('🎓 行为树指南示例已加载');
|
||||
}
|
||||
|
||||
private initializeBehaviorTree() {
|
||||
try {
|
||||
// 这里应该从JSON文件加载完整的行为树配置
|
||||
// 为了演示,我们使用简化版本
|
||||
const config: BehaviorTreeJSONConfig = {
|
||||
nodes: [
|
||||
{
|
||||
id: "root_1",
|
||||
type: "root",
|
||||
name: "行为树指南根",
|
||||
children: ["selector_main"]
|
||||
},
|
||||
{
|
||||
id: "selector_main",
|
||||
type: "selector",
|
||||
name: "主选择器",
|
||||
properties: { abortType: "LowerPriority" },
|
||||
children: ["sequence_combat", "sequence_patrol", "sequence_idle"]
|
||||
},
|
||||
{
|
||||
id: "sequence_combat",
|
||||
type: "sequence",
|
||||
name: "战斗序列",
|
||||
children: ["condition_enemy", "action_attack"]
|
||||
},
|
||||
{
|
||||
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_patrol",
|
||||
type: "sequence",
|
||||
name: "巡逻序列",
|
||||
children: ["action_patrol", "wait_patrol"]
|
||||
},
|
||||
{
|
||||
id: "action_patrol",
|
||||
type: "set-blackboard-value",
|
||||
name: "执行巡逻",
|
||||
properties: {
|
||||
variableName: "lastAction",
|
||||
value: "{{state}}_执行中"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "wait_patrol",
|
||||
type: "wait-action",
|
||||
name: "巡逻等待",
|
||||
properties: { waitTime: 1 }
|
||||
},
|
||||
{
|
||||
id: "sequence_idle",
|
||||
type: "sequence",
|
||||
name: "闲置序列",
|
||||
children: ["action_idle", "wait_idle"]
|
||||
},
|
||||
{
|
||||
id: "action_idle",
|
||||
type: "log-action",
|
||||
name: "状态报告",
|
||||
properties: {
|
||||
message: "状态报告 - 当前: {{state}}, 上次动作: {{lastAction}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "wait_idle",
|
||||
type: "wait-action",
|
||||
name: "闲置等待",
|
||||
properties: { waitTime: 2 }
|
||||
}
|
||||
],
|
||||
blackboard: [
|
||||
{
|
||||
name: "state",
|
||||
type: "string",
|
||||
value: "patrol",
|
||||
description: "当前状态"
|
||||
},
|
||||
{
|
||||
name: "lastAction",
|
||||
type: "string",
|
||||
value: "",
|
||||
description: "最后执行的动作"
|
||||
},
|
||||
{
|
||||
name: "health",
|
||||
type: "number",
|
||||
value: 100,
|
||||
description: "生命值"
|
||||
},
|
||||
{
|
||||
name: "energy",
|
||||
type: "number",
|
||||
value: 50,
|
||||
description: "能量值"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// 创建执行上下文
|
||||
const executionContext = {
|
||||
node: this.node,
|
||||
component: this,
|
||||
log: (message: string, level: string = 'info') => {
|
||||
this.addLog(`🤖 [${level.toUpperCase()}] ${message}`);
|
||||
}
|
||||
};
|
||||
|
||||
// 🎯 使用 BehaviorTreeBuilder 一键创建
|
||||
const result = BehaviorTreeBuilder.fromBehaviorTreeConfig(config, executionContext);
|
||||
|
||||
this.behaviorTree = result.tree;
|
||||
this.blackboard = result.blackboard;
|
||||
|
||||
this.updateStatus('完整行为树指南已准备就绪');
|
||||
this.addLog('✅ 行为树创建成功(高级特性版本)');
|
||||
this.addLog(`📊 包含 ${config.nodes.length} 个节点`);
|
||||
this.addLog(`📋 包含 ${config.blackboard.length} 个黑板变量`);
|
||||
|
||||
// 显示初始状态
|
||||
this.logBlackboardStatus();
|
||||
|
||||
} catch (error) {
|
||||
console.error('初始化行为树失败:', error);
|
||||
this.updateStatus('初始化失败: ' + error.message);
|
||||
this.addLog('❌ 行为树初始化失败: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
private toggleExecution() {
|
||||
if (!this.behaviorTree) {
|
||||
this.addLog('❌ 行为树未准备好');
|
||||
return;
|
||||
}
|
||||
|
||||
this.isRunning = !this.isRunning;
|
||||
|
||||
if (this.isRunning) {
|
||||
this.behaviorTree.reset();
|
||||
this.updateStatus('执行中...');
|
||||
this.addLog('🚀 开始执行完整行为树指南');
|
||||
if (this.controlButton) {
|
||||
this.controlButton.getComponentInChildren(Label).string = '停止';
|
||||
}
|
||||
} else {
|
||||
this.updateStatus('已停止');
|
||||
this.addLog('⏹️ 行为树执行已停止');
|
||||
if (this.controlButton) {
|
||||
this.controlButton.getComponentInChildren(Label).string = '开始';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private switchState() {
|
||||
if (!this.blackboard) return;
|
||||
|
||||
this.currentStateIndex = (this.currentStateIndex + 1) % this.states.length;
|
||||
const newState = this.states[this.currentStateIndex];
|
||||
|
||||
this.blackboard.setValue('state', newState);
|
||||
this.addLog(`🔄 切换状态到: ${newState}`);
|
||||
this.logBlackboardStatus();
|
||||
}
|
||||
|
||||
update(deltaTime: number) {
|
||||
if (!this.isRunning || !this.behaviorTree) return;
|
||||
|
||||
try {
|
||||
this.behaviorTree.tick(deltaTime);
|
||||
} catch (error) {
|
||||
console.error('行为树执行出错:', error);
|
||||
this.addLog('❌ 执行出错: ' + error.message);
|
||||
this.isRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
private logBlackboardStatus() {
|
||||
if (!this.blackboard) return;
|
||||
|
||||
const variables = ['state', 'lastAction', 'health', 'energy'];
|
||||
const status = variables.map(name => {
|
||||
const value = this.blackboard.getValue(name, 'undefined');
|
||||
return `${name}:${value}`;
|
||||
}).join(', ');
|
||||
|
||||
this.addLog(`📊 黑板状态: ${status}`);
|
||||
}
|
||||
|
||||
private updateStatus(status: string) {
|
||||
if (this.statusLabel) {
|
||||
this.statusLabel.string = status;
|
||||
}
|
||||
}
|
||||
|
||||
private addLog(message: string) {
|
||||
this.logs.push(`[${new Date().toLocaleTimeString()}] ${message}`);
|
||||
|
||||
// 只保留最新的20条日志
|
||||
if (this.logs.length > 20) {
|
||||
this.logs.shift();
|
||||
}
|
||||
|
||||
if (this.logLabel) {
|
||||
this.logLabel.string = this.logs.join('\n');
|
||||
}
|
||||
|
||||
console.log('[BehaviorTreeGuide]', message);
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
this.isRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 完整指南特色功能说明:
|
||||
*
|
||||
* 1. 高级节点类型:
|
||||
* - Repeater: 无限重复巡逻行为
|
||||
* - Conditional Decorator: 带条件的装饰器
|
||||
* - Inverter: 反转子节点结果
|
||||
*
|
||||
* 2. 黑板变量引用:
|
||||
* - {{state}}: 动态引用当前状态
|
||||
* - {{health}}: 显示生命值
|
||||
* - {{lastAction}}: 跟踪最后动作
|
||||
*
|
||||
* 3. 复杂行为逻辑:
|
||||
* - 巡逻:重复执行,状态检查
|
||||
* - 战斗:敌人检测,攻击防御
|
||||
* - 闲置:状态报告,定时等待
|
||||
*
|
||||
* 4. 交互功能:
|
||||
* - 状态切换按钮
|
||||
* - 开始/停止控制
|
||||
* - 实时日志显示
|
||||
* - 黑板变量监控
|
||||
*/
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "0403f4d3-2985-4452-928e-d0535cea8155",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -1,818 +0,0 @@
|
||||
{
|
||||
"nodes": [
|
||||
{
|
||||
"id": "root_1",
|
||||
"type": "root",
|
||||
"name": "行为树指南根",
|
||||
"icon": "🌳",
|
||||
"x": 1270,
|
||||
"y": 50,
|
||||
"children": [
|
||||
"selector_main"
|
||||
],
|
||||
"properties": {},
|
||||
"canHaveChildren": true,
|
||||
"canHaveParent": false,
|
||||
"hasError": false
|
||||
},
|
||||
{
|
||||
"id": "selector_main",
|
||||
"type": "selector",
|
||||
"name": "主选择器",
|
||||
"icon": "?",
|
||||
"x": 1280,
|
||||
"y": 180,
|
||||
"children": [
|
||||
"repeater_patrol",
|
||||
"selector_combat",
|
||||
"sequence_idle"
|
||||
],
|
||||
"properties": {
|
||||
"abortType": {
|
||||
"name": "中止类型",
|
||||
"type": "select",
|
||||
"value": "LowerPriority",
|
||||
"description": "决定节点在何种情况下会被中止",
|
||||
"options": [
|
||||
"None",
|
||||
"LowerPriority",
|
||||
"Self",
|
||||
"Both"
|
||||
],
|
||||
"required": false
|
||||
}
|
||||
},
|
||||
"canHaveChildren": true,
|
||||
"canHaveParent": true,
|
||||
"hasError": false
|
||||
},
|
||||
{
|
||||
"id": "repeater_patrol",
|
||||
"type": "repeater",
|
||||
"name": "巡逻重复器",
|
||||
"icon": "🔄",
|
||||
"x": 510,
|
||||
"y": 360,
|
||||
"children": [
|
||||
"sequence_patrol"
|
||||
],
|
||||
"properties": {
|
||||
"count": {
|
||||
"name": "重复次数",
|
||||
"type": "number",
|
||||
"value": -1,
|
||||
"description": "重复执行次数,-1表示无限重复,必须是正整数",
|
||||
"required": true
|
||||
},
|
||||
"continueOnFailure": {
|
||||
"name": "失败时继续",
|
||||
"type": "boolean",
|
||||
"value": true,
|
||||
"description": "子节点失败时是否继续重复",
|
||||
"required": false
|
||||
},
|
||||
"delayBetween": {
|
||||
"name": "重复间隔",
|
||||
"type": "boolean",
|
||||
"value": false,
|
||||
"description": "重复之间是否有延迟",
|
||||
"required": false
|
||||
}
|
||||
},
|
||||
"canHaveChildren": true,
|
||||
"canHaveParent": true,
|
||||
"hasError": false
|
||||
},
|
||||
{
|
||||
"id": "sequence_patrol",
|
||||
"type": "sequence",
|
||||
"name": "巡逻序列",
|
||||
"icon": "→",
|
||||
"x": 510,
|
||||
"y": 580,
|
||||
"children": [
|
||||
"decorator_patrol_check",
|
||||
"action_patrol"
|
||||
],
|
||||
"properties": {
|
||||
"abortType": {
|
||||
"name": "中止类型",
|
||||
"type": "select",
|
||||
"value": "None",
|
||||
"description": "决定节点在何种情况下会被中止",
|
||||
"options": [
|
||||
"None",
|
||||
"LowerPriority",
|
||||
"Self",
|
||||
"Both"
|
||||
],
|
||||
"required": false
|
||||
}
|
||||
},
|
||||
"canHaveChildren": true,
|
||||
"canHaveParent": true,
|
||||
"hasError": false
|
||||
},
|
||||
{
|
||||
"id": "decorator_patrol_check",
|
||||
"type": "conditional-decorator",
|
||||
"name": "巡逻条件检查",
|
||||
"icon": "🔀",
|
||||
"x": 400,
|
||||
"y": 760,
|
||||
"children": [
|
||||
"log_patrolling"
|
||||
],
|
||||
"properties": {
|
||||
"conditionType": {
|
||||
"name": "条件类型",
|
||||
"type": "select",
|
||||
"value": "custom",
|
||||
"description": "装饰器使用的条件类型",
|
||||
"options": [
|
||||
"custom",
|
||||
"random",
|
||||
"hasComponent",
|
||||
"hasTag",
|
||||
"isActive",
|
||||
"numericCompare",
|
||||
"propertyExists"
|
||||
],
|
||||
"required": false
|
||||
},
|
||||
"executeWhenTrue": {
|
||||
"name": "条件为真时执行",
|
||||
"type": "boolean",
|
||||
"value": true,
|
||||
"description": "条件为真时是否执行子节点",
|
||||
"required": false
|
||||
},
|
||||
"executeWhenFalse": {
|
||||
"name": "条件为假时执行",
|
||||
"type": "boolean",
|
||||
"value": false,
|
||||
"description": "条件为假时是否执行子节点",
|
||||
"required": false
|
||||
},
|
||||
"checkInterval": {
|
||||
"name": "检查间隔",
|
||||
"type": "number",
|
||||
"value": 1,
|
||||
"description": "条件检查间隔时间(秒),0表示每帧检查",
|
||||
"required": false
|
||||
}
|
||||
},
|
||||
"attachedCondition": {
|
||||
"type": "condition-custom",
|
||||
"name": "巡逻状态检查",
|
||||
"icon": "⚙️",
|
||||
"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
|
||||
}
|
||||
}
|
||||
},
|
||||
"canHaveChildren": true,
|
||||
"canHaveParent": true,
|
||||
"hasError": false
|
||||
},
|
||||
{
|
||||
"id": "log_patrolling",
|
||||
"type": "log-action",
|
||||
"name": "记录巡逻",
|
||||
"icon": "📝",
|
||||
"x": 400,
|
||||
"y": 1000,
|
||||
"children": [],
|
||||
"properties": {
|
||||
"message": {
|
||||
"name": "日志消息",
|
||||
"type": "string",
|
||||
"value": "正在执行巡逻任务,当前状态: {{state}}",
|
||||
"description": "使用{{}}引用黑板变量显示当前状态",
|
||||
"required": true
|
||||
},
|
||||
"logLevel": {
|
||||
"name": "日志级别",
|
||||
"type": "select",
|
||||
"value": "info",
|
||||
"description": "日志输出级别",
|
||||
"options": [
|
||||
"debug",
|
||||
"info",
|
||||
"warn",
|
||||
"error"
|
||||
],
|
||||
"required": false
|
||||
}
|
||||
},
|
||||
"canHaveChildren": false,
|
||||
"canHaveParent": true,
|
||||
"hasError": false
|
||||
},
|
||||
{
|
||||
"id": "action_patrol",
|
||||
"type": "set-blackboard-value",
|
||||
"name": "执行巡逻",
|
||||
"icon": "📝",
|
||||
"x": 620,
|
||||
"y": 760,
|
||||
"children": [],
|
||||
"properties": {
|
||||
"variableName": {
|
||||
"name": "变量名",
|
||||
"type": "string",
|
||||
"value": "lastAction",
|
||||
"description": "黑板变量名",
|
||||
"required": true
|
||||
},
|
||||
"value": {
|
||||
"name": "设置值",
|
||||
"type": "string",
|
||||
"value": "{{state}}_执行中",
|
||||
"description": "使用{{}}引用当前状态并添加后缀",
|
||||
"required": false
|
||||
},
|
||||
"sourceVariable": {
|
||||
"name": "源变量名",
|
||||
"type": "string",
|
||||
"value": "",
|
||||
"description": "从另一个黑板变量复制值",
|
||||
"required": false
|
||||
},
|
||||
"force": {
|
||||
"name": "强制设置",
|
||||
"type": "boolean",
|
||||
"value": false,
|
||||
"description": "是否忽略只读限制",
|
||||
"required": false
|
||||
}
|
||||
},
|
||||
"canHaveChildren": false,
|
||||
"canHaveParent": true,
|
||||
"hasError": false
|
||||
},
|
||||
{
|
||||
"id": "selector_combat",
|
||||
"type": "selector",
|
||||
"name": "战斗选择器",
|
||||
"icon": "?",
|
||||
"x": 1170,
|
||||
"y": 360,
|
||||
"children": [
|
||||
"sequence_attack",
|
||||
"sequence_defend"
|
||||
],
|
||||
"properties": {
|
||||
"abortType": {
|
||||
"name": "中止类型",
|
||||
"type": "select",
|
||||
"value": "None",
|
||||
"description": "决定节点在何种情况下会被中止",
|
||||
"options": [
|
||||
"None",
|
||||
"LowerPriority",
|
||||
"Self",
|
||||
"Both"
|
||||
],
|
||||
"required": false
|
||||
}
|
||||
},
|
||||
"canHaveChildren": true,
|
||||
"canHaveParent": true,
|
||||
"hasError": false
|
||||
},
|
||||
{
|
||||
"id": "sequence_attack",
|
||||
"type": "sequence",
|
||||
"name": "攻击序列",
|
||||
"icon": "→",
|
||||
"x": 950,
|
||||
"y": 540,
|
||||
"children": [
|
||||
"inverter_enemy",
|
||||
"action_attack"
|
||||
],
|
||||
"properties": {
|
||||
"abortType": {
|
||||
"name": "中止类型",
|
||||
"type": "select",
|
||||
"value": "Self",
|
||||
"description": "决定节点在何种情况下会被中止",
|
||||
"options": [
|
||||
"None",
|
||||
"LowerPriority",
|
||||
"Self",
|
||||
"Both"
|
||||
],
|
||||
"required": false
|
||||
}
|
||||
},
|
||||
"canHaveChildren": true,
|
||||
"canHaveParent": true,
|
||||
"hasError": false
|
||||
},
|
||||
{
|
||||
"id": "inverter_enemy",
|
||||
"type": "inverter",
|
||||
"name": "敌人检查反转",
|
||||
"icon": "!",
|
||||
"x": 840,
|
||||
"y": 720,
|
||||
"children": [
|
||||
"condition_enemy"
|
||||
],
|
||||
"properties": {},
|
||||
"canHaveChildren": true,
|
||||
"canHaveParent": true,
|
||||
"hasError": false
|
||||
},
|
||||
{
|
||||
"id": "condition_enemy",
|
||||
"type": "condition-random",
|
||||
"name": "随机敌人出现",
|
||||
"icon": "🎲",
|
||||
"x": 840,
|
||||
"y": 880,
|
||||
"children": [],
|
||||
"properties": {
|
||||
"successProbability": {
|
||||
"name": "成功概率",
|
||||
"type": "number",
|
||||
"value": 0.3,
|
||||
"description": "条件成功的概率 (0.0 - 1.0)",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
"canHaveChildren": false,
|
||||
"canHaveParent": true,
|
||||
"hasError": false
|
||||
},
|
||||
{
|
||||
"id": "action_attack",
|
||||
"type": "log-action",
|
||||
"name": "攻击动作",
|
||||
"icon": "📝",
|
||||
"x": 1060,
|
||||
"y": 720,
|
||||
"children": [],
|
||||
"properties": {
|
||||
"message": {
|
||||
"name": "日志消息",
|
||||
"type": "string",
|
||||
"value": "发动攻击!生命值: {{health}}, 能量: {{energy}}",
|
||||
"description": "使用{{}}引用显示战斗时的状态信息",
|
||||
"required": true
|
||||
},
|
||||
"logLevel": {
|
||||
"name": "日志级别",
|
||||
"type": "select",
|
||||
"value": "warn",
|
||||
"description": "日志输出级别",
|
||||
"options": [
|
||||
"debug",
|
||||
"info",
|
||||
"warn",
|
||||
"error"
|
||||
],
|
||||
"required": false
|
||||
}
|
||||
},
|
||||
"canHaveChildren": false,
|
||||
"canHaveParent": true,
|
||||
"hasError": false
|
||||
},
|
||||
{
|
||||
"id": "sequence_defend",
|
||||
"type": "sequence",
|
||||
"name": "防御序列",
|
||||
"icon": "→",
|
||||
"x": 1390,
|
||||
"y": 540,
|
||||
"children": [
|
||||
"wait_defend",
|
||||
"action_defend"
|
||||
],
|
||||
"properties": {
|
||||
"abortType": {
|
||||
"name": "中止类型",
|
||||
"type": "select",
|
||||
"value": "None",
|
||||
"description": "决定节点在何种情况下会被中止",
|
||||
"options": [
|
||||
"None",
|
||||
"LowerPriority",
|
||||
"Self",
|
||||
"Both"
|
||||
],
|
||||
"required": false
|
||||
}
|
||||
},
|
||||
"canHaveChildren": true,
|
||||
"canHaveParent": true,
|
||||
"hasError": false
|
||||
},
|
||||
{
|
||||
"id": "wait_defend",
|
||||
"type": "wait-action",
|
||||
"name": "防御准备",
|
||||
"icon": "⏰",
|
||||
"x": 1280,
|
||||
"y": 720,
|
||||
"children": [],
|
||||
"properties": {
|
||||
"waitTime": {
|
||||
"name": "等待时间",
|
||||
"type": "number",
|
||||
"value": 0.5,
|
||||
"description": "等待时间(秒),必须大于0",
|
||||
"required": true
|
||||
},
|
||||
"useExternalTime": {
|
||||
"name": "使用外部时间",
|
||||
"type": "boolean",
|
||||
"value": false,
|
||||
"description": "是否使用上下文提供的deltaTime,否则使用内部时间计算",
|
||||
"required": false
|
||||
}
|
||||
},
|
||||
"canHaveChildren": false,
|
||||
"canHaveParent": true,
|
||||
"hasError": false
|
||||
},
|
||||
{
|
||||
"id": "action_defend",
|
||||
"type": "execute-action",
|
||||
"name": "执行防御",
|
||||
"icon": "⚙️",
|
||||
"x": 1500,
|
||||
"y": 720,
|
||||
"children": [],
|
||||
"properties": {
|
||||
"actionCode": {
|
||||
"name": "动作代码",
|
||||
"type": "code",
|
||||
"value": "(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}",
|
||||
"description": "要执行的动作函数代码",
|
||||
"required": true
|
||||
},
|
||||
"actionName": {
|
||||
"name": "动作名称",
|
||||
"type": "string",
|
||||
"value": "防御动作_生命值{{health}}",
|
||||
"description": "使用{{}}引用在动作名称中显示生命值",
|
||||
"required": false
|
||||
}
|
||||
},
|
||||
"canHaveChildren": false,
|
||||
"canHaveParent": true,
|
||||
"hasError": false
|
||||
},
|
||||
{
|
||||
"id": "sequence_idle",
|
||||
"type": "sequence",
|
||||
"name": "闲置序列",
|
||||
"icon": "→",
|
||||
"x": 1940,
|
||||
"y": 360,
|
||||
"children": [
|
||||
"action_idle",
|
||||
"log_status",
|
||||
"wait_idle"
|
||||
],
|
||||
"properties": {
|
||||
"abortType": {
|
||||
"name": "中止类型",
|
||||
"type": "select",
|
||||
"value": "None",
|
||||
"description": "决定节点在何种情况下会被中止",
|
||||
"options": [
|
||||
"None",
|
||||
"LowerPriority",
|
||||
"Self",
|
||||
"Both"
|
||||
],
|
||||
"required": false
|
||||
}
|
||||
},
|
||||
"canHaveChildren": true,
|
||||
"canHaveParent": true,
|
||||
"hasError": false
|
||||
},
|
||||
{
|
||||
"id": "action_idle",
|
||||
"type": "set-blackboard-value",
|
||||
"name": "设置闲置",
|
||||
"icon": "📝",
|
||||
"x": 1720,
|
||||
"y": 540,
|
||||
"children": [],
|
||||
"properties": {
|
||||
"variableName": {
|
||||
"name": "变量名",
|
||||
"type": "string",
|
||||
"value": "state",
|
||||
"description": "黑板变量名",
|
||||
"required": true
|
||||
},
|
||||
"value": {
|
||||
"name": "设置值",
|
||||
"type": "string",
|
||||
"value": "idle",
|
||||
"description": "要设置的值(留空则使用源变量)",
|
||||
"required": false
|
||||
},
|
||||
"sourceVariable": {
|
||||
"name": "源变量名",
|
||||
"type": "string",
|
||||
"value": "",
|
||||
"description": "从另一个黑板变量复制值",
|
||||
"required": false
|
||||
},
|
||||
"force": {
|
||||
"name": "强制设置",
|
||||
"type": "boolean",
|
||||
"value": false,
|
||||
"description": "是否忽略只读限制",
|
||||
"required": false
|
||||
}
|
||||
},
|
||||
"canHaveChildren": false,
|
||||
"canHaveParent": true,
|
||||
"hasError": false
|
||||
},
|
||||
{
|
||||
"id": "log_status",
|
||||
"type": "log-action",
|
||||
"name": "状态报告",
|
||||
"icon": "📝",
|
||||
"x": 1940,
|
||||
"y": 540,
|
||||
"children": [],
|
||||
"properties": {
|
||||
"message": {
|
||||
"name": "日志消息",
|
||||
"type": "string",
|
||||
"value": "状态报告 - 当前: {{state}}, 上次动作: {{lastAction}}, 防御中: {{defendActive}}",
|
||||
"description": "完整的黑板变量引用示例,显示多个变量值",
|
||||
"required": true
|
||||
},
|
||||
"logLevel": {
|
||||
"name": "日志级别",
|
||||
"type": "select",
|
||||
"value": "debug",
|
||||
"description": "日志输出级别",
|
||||
"options": [
|
||||
"debug",
|
||||
"info",
|
||||
"warn",
|
||||
"error"
|
||||
],
|
||||
"required": false
|
||||
}
|
||||
},
|
||||
"canHaveChildren": false,
|
||||
"canHaveParent": true,
|
||||
"hasError": false
|
||||
},
|
||||
{
|
||||
"id": "wait_idle",
|
||||
"type": "wait-action",
|
||||
"name": "闲置等待",
|
||||
"icon": "⏰",
|
||||
"x": 2160,
|
||||
"y": 540,
|
||||
"children": [],
|
||||
"properties": {
|
||||
"waitTime": {
|
||||
"name": "等待时间",
|
||||
"type": "number",
|
||||
"value": 3,
|
||||
"description": "等待时间(秒),必须大于0",
|
||||
"required": true
|
||||
},
|
||||
"useExternalTime": {
|
||||
"name": "使用外部时间",
|
||||
"type": "boolean",
|
||||
"value": false,
|
||||
"description": "是否使用上下文提供的deltaTime,否则使用内部时间计算",
|
||||
"required": false
|
||||
}
|
||||
},
|
||||
"canHaveChildren": false,
|
||||
"canHaveParent": true,
|
||||
"hasError": false
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"id": "root_1-selector_main",
|
||||
"sourceId": "root_1",
|
||||
"targetId": "selector_main",
|
||||
"path": "M 1350.000006198883 125.66623544692993 C 1350.000006198883 155.66623544692993 1360.000006198883 155.04567861557007 1360.000006198883 185.04567861557007",
|
||||
"active": false
|
||||
},
|
||||
{
|
||||
"id": "selector_main-repeater_patrol",
|
||||
"sourceId": "selector_main",
|
||||
"targetId": "repeater_patrol",
|
||||
"path": "M 1360.000006198883 274.9542908668518 C 1360.000006198883 320.00000619888306 590.000006198883 320.00000619888306 590.000006198883 365.0457215309143",
|
||||
"active": false
|
||||
},
|
||||
{
|
||||
"id": "selector_main-selector_combat",
|
||||
"sourceId": "selector_main",
|
||||
"targetId": "selector_combat",
|
||||
"path": "M 1360.000006198883 274.9542908668518 C 1360.000006198883 320.00000619888306 1250.000006198883 320.00000619888306 1250.000006198883 365.0457215309143",
|
||||
"active": false
|
||||
},
|
||||
{
|
||||
"id": "selector_main-sequence_idle",
|
||||
"sourceId": "selector_main",
|
||||
"targetId": "sequence_idle",
|
||||
"path": "M 1360.000006198883 274.9542908668518 C 1360.000006198883 320.00000619888306 2020.0001282691956 320.00000619888306 2020.0001282691956 365.0457215309143",
|
||||
"active": false
|
||||
},
|
||||
{
|
||||
"id": "repeater_patrol-sequence_patrol",
|
||||
"sourceId": "repeater_patrol",
|
||||
"targetId": "sequence_patrol",
|
||||
"path": "M 590.000006198883 454.9542908668518 C 590.000006198883 519.9999756813049 590.000006198883 519.9999756813049 590.000006198883 585.045660495758",
|
||||
"active": false
|
||||
},
|
||||
{
|
||||
"id": "sequence_patrol-decorator_patrol_check",
|
||||
"sourceId": "sequence_patrol",
|
||||
"targetId": "decorator_patrol_check",
|
||||
"path": "M 590.000006198883 674.9542908668518 C 590.000006198883 721.4701294898987 510.00000619888306 721.4701294898987 510.00000619888306 767.9859681129456",
|
||||
"active": false
|
||||
},
|
||||
{
|
||||
"id": "sequence_patrol-action_patrol",
|
||||
"sourceId": "sequence_patrol",
|
||||
"targetId": "action_patrol",
|
||||
"path": "M 590.000006198883 674.9542908668518 C 590.000006198883 720.0783143043518 700.000006198883 720.0783143043518 700.000006198883 765.2023377418518",
|
||||
"active": false
|
||||
},
|
||||
{
|
||||
"id": "decorator_patrol_check-log_patrolling",
|
||||
"sourceId": "decorator_patrol_check",
|
||||
"targetId": "log_patrolling",
|
||||
"path": "M 510.00000619888306 934.6140809059143 C 510.00000619888306 969.908209323883 480.00000619888306 969.908209323883 480.00000619888306 1005.2023377418518",
|
||||
"active": false
|
||||
},
|
||||
{
|
||||
"id": "selector_combat-sequence_attack",
|
||||
"sourceId": "selector_combat",
|
||||
"targetId": "sequence_attack",
|
||||
"path": "M 1250.000006198883 454.9542908668518 C 1250.000006198883 499.99997568130493 1030.000006198883 499.99997568130493 1030.000006198883 545.045660495758",
|
||||
"active": false
|
||||
},
|
||||
{
|
||||
"id": "selector_combat-sequence_defend",
|
||||
"sourceId": "selector_combat",
|
||||
"targetId": "sequence_defend",
|
||||
"path": "M 1250.000006198883 454.9542908668518 C 1250.000006198883 499.99997568130493 1470.000006198883 499.99997568130493 1470.000006198883 545.045660495758",
|
||||
"active": false
|
||||
},
|
||||
{
|
||||
"id": "sequence_attack-inverter_enemy",
|
||||
"sourceId": "sequence_attack",
|
||||
"targetId": "inverter_enemy",
|
||||
"path": "M 1030.000006198883 634.9542908668518 C 1030.000006198883 679.644049167633 920.000006198883 679.644049167633 920.000006198883 724.3338074684143",
|
||||
"active": false
|
||||
},
|
||||
{
|
||||
"id": "sequence_attack-action_attack",
|
||||
"sourceId": "sequence_attack",
|
||||
"targetId": "action_attack",
|
||||
"path": "M 1030.000006198883 634.9542908668518 C 1030.000006198883 680.0783143043518 1140.000006198883 680.0783143043518 1140.000006198883 725.2023377418518",
|
||||
"active": false
|
||||
},
|
||||
{
|
||||
"id": "inverter_enemy-condition_enemy",
|
||||
"sourceId": "inverter_enemy",
|
||||
"targetId": "condition_enemy",
|
||||
"path": "M 920.000006198883 795.6662049293518 C 920.000006198883 840.355963230133 920.000006198883 840.355963230133 920.000006198883 885.0457215309143",
|
||||
"active": false
|
||||
},
|
||||
{
|
||||
"id": "sequence_defend-wait_defend",
|
||||
"sourceId": "sequence_defend",
|
||||
"targetId": "wait_defend",
|
||||
"path": "M 1470.000006198883 634.9542908668518 C 1470.000006198883 680.000006198883 1360.000006198883 680.000006198883 1360.000006198883 725.0457215309143",
|
||||
"active": false
|
||||
},
|
||||
{
|
||||
"id": "sequence_defend-action_defend",
|
||||
"sourceId": "sequence_defend",
|
||||
"targetId": "action_defend",
|
||||
"path": "M 1470.000006198883 634.9542908668518 C 1470.000006198883 680.0783143043518 1580.000006198883 680.0783143043518 1580.000006198883 725.2023377418518",
|
||||
"active": false
|
||||
},
|
||||
{
|
||||
"id": "sequence_idle-action_idle",
|
||||
"sourceId": "sequence_idle",
|
||||
"targetId": "action_idle",
|
||||
"path": "M 2020.0001282691956 454.9542908668518 C 2020.0001282691956 500.0782837867737 1800.0001282691956 500.0782837867737 1800.0001282691956 545.2022767066956",
|
||||
"active": false
|
||||
},
|
||||
{
|
||||
"id": "sequence_idle-log_status",
|
||||
"sourceId": "sequence_idle",
|
||||
"targetId": "log_status",
|
||||
"path": "M 2020.0001282691956 454.9542908668518 C 2020.0001282691956 500.0782837867737 2020.0001282691956 500.0782837867737 2020.0001282691956 545.2022767066956",
|
||||
"active": false
|
||||
},
|
||||
{
|
||||
"id": "sequence_idle-wait_idle",
|
||||
"sourceId": "sequence_idle",
|
||||
"targetId": "wait_idle",
|
||||
"path": "M 2020.0001282691956 454.9542908668518 C 2020.0001282691956 499.99997568130493 2240.0001282691956 499.99997568130493 2240.0001282691956 545.045660495758",
|
||||
"active": false
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"name": "assets/resources/behavior-tree-examples-guide",
|
||||
"created": "2025-06-22T11:04:28.781Z",
|
||||
"version": "1.0"
|
||||
},
|
||||
"blackboard": [
|
||||
{
|
||||
"name": "state",
|
||||
"type": "string",
|
||||
"value": "patrol",
|
||||
"defaultValue": "idle",
|
||||
"description": "当前状态",
|
||||
"group": "核心状态",
|
||||
"readOnly": false,
|
||||
"constraints": {
|
||||
"allowedValues": [
|
||||
"idle",
|
||||
"patrol",
|
||||
"combat",
|
||||
"defend"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "lastAction",
|
||||
"type": "string",
|
||||
"value": "",
|
||||
"defaultValue": "",
|
||||
"description": "最后执行的动作",
|
||||
"group": "核心状态",
|
||||
"readOnly": false,
|
||||
"constraints": {}
|
||||
},
|
||||
{
|
||||
"name": "defendActive",
|
||||
"type": "boolean",
|
||||
"value": false,
|
||||
"defaultValue": false,
|
||||
"description": "是否正在防御",
|
||||
"group": "战斗状态",
|
||||
"readOnly": false,
|
||||
"constraints": {}
|
||||
},
|
||||
{
|
||||
"name": "health",
|
||||
"type": "number",
|
||||
"value": 100,
|
||||
"defaultValue": 100,
|
||||
"description": "生命值",
|
||||
"group": "属性",
|
||||
"readOnly": false,
|
||||
"constraints": {
|
||||
"min": 0,
|
||||
"max": 100,
|
||||
"step": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "energy",
|
||||
"type": "number",
|
||||
"value": 50,
|
||||
"defaultValue": 100,
|
||||
"description": "能量值",
|
||||
"group": "属性",
|
||||
"readOnly": false,
|
||||
"constraints": {
|
||||
"min": 0,
|
||||
"max": 100,
|
||||
"step": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"ver": "2.0.1",
|
||||
"importer": "json",
|
||||
"imported": true,
|
||||
"uuid": "ba6c564a-c5c5-4dc7-ba95-9f0279e0bd66",
|
||||
"files": [
|
||||
".json"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -1,283 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"ver": "2.0.1",
|
||||
"importer": "json",
|
||||
"imported": true,
|
||||
"uuid": "4d7244e6-4be6-46a0-9e38-6915004177e7",
|
||||
"files": [
|
||||
".json"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -74,12 +74,12 @@ export class BehaviorTreeExample extends Component {
|
||||
try {
|
||||
this.updateStatus('加载行为树配置...');
|
||||
|
||||
// 从resources目录加载test.bt.json文件
|
||||
resources.load('test.bt', JsonAsset, (err, jsonAsset: JsonAsset) => {
|
||||
// 从resources目录加载simple-example.bt.json文件
|
||||
resources.load('simple-example.bt', JsonAsset, (err, jsonAsset: JsonAsset) => {
|
||||
if (err) {
|
||||
console.error('加载行为树配置失败:', err);
|
||||
this.updateStatus('加载失败: ' + err.message);
|
||||
this.updateLog('❌ 加载test.bt.json失败: ' + err.message);
|
||||
this.updateLog('❌ 加载simple-example.bt.json失败: ' + err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user