更新rts示例代码(矿工自动采矿)

This commit is contained in:
YHH
2025-06-24 23:51:59 +08:00
parent 0f18a1979e
commit 01084a8897
27 changed files with 1561 additions and 8904 deletions

View File

@@ -1,17 +1,20 @@
import { _decorator, Component, resources, JsonAsset } from 'cc';
import { BehaviorTree, BehaviorTreeBuilder, Blackboard, BehaviorTreeJSONConfig } from '@esengine/ai';
import { _decorator, Component, resources, JsonAsset, Vec3 } from 'cc';
import { BehaviorTree, BehaviorTreeBuilder, Blackboard, BehaviorTreeJSONConfig, ExecutionContext, EventRegistry } from '@esengine/ai';
import { UnitController } from './UnitController';
import { RTSBehaviorHandler } from './RTSBehaviorHandler';
const { ccclass, property } = _decorator;
/**
* 执行上下文接口
* 游戏执行上下文接口
* 继承框架的ExecutionContext添加游戏特定的属性
*/
interface GameExecutionContext {
blackboard?: Blackboard;
interface GameExecutionContext extends ExecutionContext {
unitController: UnitController;
gameObject: any;
[key: string]: any;
eventRegistry?: EventRegistry;
// 确保继承索引签名
[key: string]: unknown;
}
/**
@@ -24,16 +27,18 @@ export class BehaviorTreeManager extends Component {
debugMode: boolean = true;
@property
tickInterval: number = 0.1; // 行为树更新间隔(秒)
tickInterval: number = 0.1; // 行为树更新间隔(秒)- 10fps更新频率平衡性能和响应性
private behaviorTree: BehaviorTree<GameExecutionContext> | null = null;
private blackboard: Blackboard | null = null;
private context: GameExecutionContext | null = null;
private eventRegistry: EventRegistry | null = null;
private isLoaded: boolean = false;
private isRunning: boolean = false;
private lastTickTime: number = 0;
private unitController: UnitController | null = null;
private currentBehaviorTreeName: string = '';
private behaviorHandler: RTSBehaviorHandler | null = null;
/**
* 初始化行为树
@@ -42,12 +47,22 @@ export class BehaviorTreeManager extends Component {
this.currentBehaviorTreeName = behaviorTreeName;
this.unitController = unitController;
// 获取RTSBehaviorHandler组件
this.behaviorHandler = this.getComponent(RTSBehaviorHandler);
if (!this.behaviorHandler) {
console.error(`BehaviorTreeManager: 未找到RTSBehaviorHandler组件 - ${this.node.name}`);
return;
}
try {
await this.loadBehaviorTree(behaviorTreeName);
this.setupBlackboard();
this.isLoaded = true;
this.isRunning = true;
console.log(`行为树初始化成功: ${behaviorTreeName}`);
console.log(`行为树初始化成功: ${behaviorTreeName} for ${this.unitController.node.name}`);
console.log(` - 行为树: ${this.behaviorTree ? '已创建' : '未创建'}`);
console.log(` - 黑板变量: ${this.blackboard ? '已创建' : '未创建'}`);
console.log(` - 运行状态: ${this.isRunning ? '运行中' : '已停止'}`);
} catch (error) {
console.error(`行为树初始化失败: ${behaviorTreeName}`, error);
}
@@ -59,6 +74,7 @@ export class BehaviorTreeManager extends Component {
private async loadBehaviorTree(behaviorTreeName: string): Promise<void> {
return new Promise((resolve, reject) => {
const jsonPath = `${behaviorTreeName}.bt`;
console.log(`🔍 尝试加载行为树文件: ${jsonPath}`);
resources.load(jsonPath, JsonAsset, (err, asset) => {
if (err) {
@@ -72,15 +88,17 @@ export class BehaviorTreeManager extends Component {
// 创建执行上下文
this.blackboard = new Blackboard();
this.eventRegistry = this.createEventRegistry();
this.context = {
blackboard: this.blackboard,
unitController: this.unitController!,
gameObject: this.node
};
gameObject: this.node,
eventRegistry: this.eventRegistry
} as GameExecutionContext;
// 从JSON数据创建行为树
const buildResult = BehaviorTreeBuilder.fromBehaviorTreeConfig(behaviorTreeData, this.context);
this.behaviorTree = buildResult.tree as BehaviorTree<GameExecutionContext>;
const buildResult = BehaviorTreeBuilder.fromBehaviorTreeConfig<GameExecutionContext>(behaviorTreeData, this.context);
this.behaviorTree = buildResult.tree;
this.blackboard = buildResult.blackboard;
resolve();
@@ -92,35 +110,70 @@ export class BehaviorTreeManager extends Component {
});
}
/**
* 创建事件注册表
*/
private createEventRegistry(): EventRegistry {
const registry = new EventRegistry();
// 注册简化的矿工行为事件处理器
const eventHandlers = {
// 矿工核心行为
'find-and-mine-ore': (context: any, params?: any) => this.callBehaviorHandler('onFindAndMineOre', params),
'store-ore': (context: any, params?: any) => this.callBehaviorHandler('onStoreOre', params),
'idle-behavior': (context: any, params?: any) => this.callBehaviorHandler('onIdleBehavior', params)
};
// 将事件处理器注册到EventRegistry
Object.entries(eventHandlers).forEach(([eventName, handler]) => {
registry.registerAction(eventName, handler);
});
return registry;
}
/**
* 调用行为处理器的方法
*/
private callBehaviorHandler(methodName: string, params: any = {}): string {
if (!this.behaviorHandler) {
console.error(`BehaviorTreeManager: RTSBehaviorHandler未初始化 - ${this.node.name}`);
return 'failure';
}
try {
// 直接调用RTSBehaviorHandler的方法
const method = (this.behaviorHandler as any)[methodName];
if (typeof method === 'function') {
console.log(`🎯 调用行为处理器: ${methodName} (${this.node.name})`);
const result = method.call(this.behaviorHandler, params);
console.log(`📤 行为处理器返回: ${methodName} -> "${result}" (${this.node.name})`);
return result || 'success'; // 确保有返回值
} else {
console.error(`BehaviorTreeManager: 方法不存在: ${methodName}`);
return 'failure';
}
} catch (error) {
console.error(`BehaviorTreeManager: 调用方法失败: ${methodName}`, error);
return 'failure';
}
}
/**
* 设置黑板基础信息
*/
private setupBlackboard() {
if (!this.unitController || !this.blackboard) return;
// 设置单位基础信息
this.blackboard.setValue('entityName', this.node.name);
// 设置矿工基础信息
this.blackboard.setValue('unitType', this.unitController.unitType);
this.blackboard.setValue('maxHealth', this.unitController.maxHealth);
this.blackboard.setValue('currentHealth', this.unitController.currentHealth);
this.blackboard.setValue('moveSpeed', this.unitController.moveSpeed);
this.blackboard.setValue('attackRange', this.unitController.attackRange);
this.blackboard.setValue('attackDamage', this.unitController.attackDamage);
this.blackboard.setValue('attackCooldown', this.unitController.attackCooldown);
// 设置时间信息
this.blackboard.setValue('currentTime', Date.now() / 1000);
this.blackboard.setValue('deltaTime', 0.016);
this.blackboard.setValue('worldPosition', this.node.worldPosition);
// 设置初始状态
this.blackboard.setValue('currentCommand', 'idle');
this.blackboard.setValue('maxHealth', this.unitController.maxHealth);
this.blackboard.setValue('currentCommand', 'mine');
this.blackboard.setValue('hasOre', false);
this.blackboard.setValue('hasTarget', false);
this.blackboard.setValue('isSelected', false);
// 设置单位控制器引用,供行为树节点使用
this.blackboard.setValue('unitController', this.unitController);
this.blackboard.setValue('gameObject', this.node);
this.blackboard.setValue('targetPosition', null);
this.blackboard.setValue('isMoving', false);
}
/**
@@ -165,45 +218,20 @@ export class BehaviorTreeManager extends Component {
this.lastTickTime = 0;
// 更新黑板中的时间信息
this.blackboard.setValue('deltaTime', deltaTime);
this.blackboard.setValue('currentTime', Date.now() / 1000);
this.blackboard.setValue('worldPosition', this.node.worldPosition);
// 更新单位状态信息
// 更新矿工状态信息
if (this.unitController) {
this.blackboard.setValue('currentHealth', this.unitController.currentHealth);
this.blackboard.setValue('healthPercentage', this.unitController.currentHealth / this.unitController.maxHealth);
this.blackboard.setValue('isLowHealth', this.unitController.currentHealth < this.unitController.maxHealth * 0.3);
this.blackboard.setValue('currentCommand', this.unitController.currentCommand);
this.blackboard.setValue('isSelected', this.unitController.isSelected);
this.blackboard.setValue('hasTarget', this.unitController.targetPosition && !this.unitController.targetPosition.equals(Vec3.ZERO));
this.blackboard.setValue('targetPosition', this.unitController.targetPosition);
this.blackboard.setValue('targetNode', this.unitController.targetNode);
// 更新距离信息
if (this.unitController.targetPosition) {
const distance = this.node.worldPosition.subtract(this.unitController.targetPosition).length();
this.blackboard.setValue('distanceToTarget', distance);
this.blackboard.setValue('isInAttackRange', distance <= this.unitController.attackRange);
this.blackboard.setValue('isCloseToTarget', distance <= 1.0);
}
// 更新状态标志
this.blackboard.setValue('isIdle', this.unitController.currentCommand === 'idle');
this.blackboard.setValue('isMoving', this.unitController.currentCommand === 'move');
this.blackboard.setValue('isAttacking', this.unitController.currentCommand === 'attack');
this.blackboard.setValue('isGathering', this.unitController.currentCommand === 'gather');
this.blackboard.setValue('isPatrolling', this.unitController.currentCommand === 'patrol');
this.blackboard.setValue('isMoving', this.unitController.targetPosition && !this.unitController.targetPosition.equals(Vec3.ZERO));
}
// 执行行为树
try {
this.behaviorTree.tick(deltaTime);
if (this.debugMode && Math.random() < 0.01) { // 1%的概率打印调试信息
console.log(`行为树执行完成, 单位: ${this.node.name}`);
}
} catch (error) {
console.error(`行为树执行错误:`, error);
console.error(`行为树执行错误: ${this.node.name}`, error);
}
}