更新example
This commit is contained in:
@@ -0,0 +1,314 @@
|
||||
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. 交互功能:
|
||||
* - 状态切换按钮
|
||||
* - 开始/停止控制
|
||||
* - 实时日志显示
|
||||
* - 黑板变量监控
|
||||
*/
|
||||
Reference in New Issue
Block a user