Files
esengine/extensions/cocos/cocos-ecs/assets/scripts/components/BehaviorTreeComponent.ts

165 lines
5.2 KiB
TypeScript
Raw Normal View History

2025-06-24 19:34:37 +08:00
import { Node, resources, JsonAsset } from 'cc';
import { BehaviorTree, BehaviorTreeBuilder, Blackboard, TaskStatus, BehaviorTreeJSONConfig } from '@esengine/ai';
import { ECSComponent } from './UnitComponent';
/**
* - ECS组件
*/
export class BehaviorTreeComponent extends ECSComponent {
public behaviorTreeFile: string = '';
public cocosNode: Node | null = null;
private behaviorTree: BehaviorTree<any> | null = null;
private blackboard: Blackboard | null = null;
private context: any = null;
private isLoaded: boolean = false;
private isRunning: boolean = false;
private lastTickTime: number = 0;
private tickInterval: number = 0.1; // 行为树更新间隔(秒)
/**
*
*/
async initialize() {
if (!this.behaviorTreeFile) {
console.error('行为树文件路径未设置');
return;
}
try {
await this.loadBehaviorTree();
this.setupBlackboard();
this.isLoaded = true;
this.isRunning = true;
console.log(`行为树组件初始化成功: ${this.behaviorTreeFile}`);
} catch (error) {
console.error(`行为树组件初始化失败: ${this.behaviorTreeFile}`, error);
}
}
/**
*
*/
private async loadBehaviorTree(): Promise<void> {
return new Promise((resolve, reject) => {
// 移除.btree扩展名使用.bt.json
const jsonPath = this.behaviorTreeFile.replace('.btree', '.bt.json');
resources.load(jsonPath, JsonAsset, (err, asset) => {
if (err) {
console.error(`加载行为树文件失败: ${jsonPath}`, err);
reject(err);
return;
}
try {
const treeData = asset.json as BehaviorTreeJSONConfig;
this.buildBehaviorTree(treeData);
resolve();
} catch (buildError) {
console.error(`构建行为树失败: ${jsonPath}`, buildError);
reject(buildError);
}
});
});
}
/**
*
*/
private buildBehaviorTree(treeData: BehaviorTreeJSONConfig) {
// 创建基础执行上下文
const baseContext = {
cocosNode: this.cocosNode,
unitComponent: this
};
// 使用@esengine/ai的BehaviorTreeBuilder构建行为树
// 这会自动创建黑板并设置所有配置
const result = BehaviorTreeBuilder.fromBehaviorTreeConfig(treeData, baseContext);
this.behaviorTree = result.tree;
this.blackboard = result.blackboard;
this.context = result.context;
}
/**
*
*/
private setupBlackboard() {
if (!this.blackboard || !this.cocosNode) return;
// 注意:只设置行为树中实际定义的变量
// 这些变量需要在对应的.btree文件的blackboard数组中预先定义
// 设置基础信息 - 注释掉未在行为树中定义的变量
// this.blackboard.setValue('entityName', this.cocosNode.name);
// this.blackboard.setValue('currentTime', Date.now() / 1000);
// this.blackboard.setValue('deltaTime', 0.016);
// this.blackboard.setValue('worldPosition', this.cocosNode.worldPosition);
console.log('BehaviorTreeComponent黑板设置完成未设置任何变量以避免警告');
2025-06-24 19:34:37 +08:00
}
/**
*
*/
update(deltaTime: number) {
if (!this.isLoaded || !this.isRunning || !this.behaviorTree || !this.context) return;
// 控制更新频率
this.lastTickTime += deltaTime;
if (this.lastTickTime < this.tickInterval) return;
this.lastTickTime = 0;
// 更新黑板中的时间信息 - 注释掉未在行为树中定义的变量
2025-06-24 19:34:37 +08:00
if (this.blackboard) {
// 只更新行为树中实际定义的变量
// this.blackboard.setValue('deltaTime', deltaTime);
// this.blackboard.setValue('currentTime', Date.now() / 1000);
// if (this.cocosNode) {
// this.blackboard.setValue('worldPosition', this.cocosNode.worldPosition);
// }
2025-06-24 19:34:37 +08:00
}
// 执行行为树
try {
this.behaviorTree.tick();
} catch (error) {
console.error(`行为树执行错误:`, error);
}
}
/**
*
*/
getBlackboard(): Blackboard | null {
return this.blackboard;
}
/**
*
*/
pause() {
this.isRunning = false;
}
/**
*
*/
resume() {
if (this.isLoaded) {
this.isRunning = true;
}
}
/**
*
*/
stop() {
this.isRunning = false;
if (this.behaviorTree) {
this.behaviorTree.reset();
}
}
}