Feature/ecs behavior tree (#188)

* feat(behavior-tree): 完全 ECS 化的行为树系统

* feat(editor-app): 添加行为树可视化编辑器

* chore: 移除 Cocos Creator 扩展目录

* feat(editor-app): 行为树编辑器功能增强

* fix(editor-app): 修复 TypeScript 类型错误

* feat(editor-app): 使用 FlexLayout 重构面板系统并优化资产浏览器

* feat(editor-app): 改进编辑器UI样式并修复行为树执行顺序

* feat(behavior-tree,editor-app): 添加装饰器系统并优化编辑器性能

* feat(behavior-tree,editor-app): 添加属性绑定系统

* feat(editor-app,behavior-tree): 优化编辑器UI并改进行为树功能

* feat(editor-app,behavior-tree): 添加全局黑板系统并增强资产浏览器功能

* feat(behavior-tree,editor-app): 添加运行时资产导出系统

* feat(behavior-tree,editor-app): 添加SubTree系统和资产选择器

* feat(behavior-tree,editor-app): 优化系统架构并改进编辑器文件管理

* fix(behavior-tree,editor-app): 修复SubTree节点错误显示空节点警告

* fix(editor-app): 修复局部黑板类型定义文件扩展名错误
This commit is contained in:
YHH
2025-10-27 09:29:11 +08:00
committed by GitHub
parent 0cd99209c4
commit 009f8af4e1
234 changed files with 21824 additions and 15295 deletions

View File

@@ -0,0 +1,179 @@
import { Entity } from '@esengine/ecs-framework';
import { BehaviorTreeNode } from './Components/BehaviorTreeNode';
import { ActiveNode } from './Components/ActiveNode';
import { TaskStatus } from './Types/TaskStatus';
/**
* 行为树启动/停止辅助类
*
* 提供便捷方法来启动、停止和暂停行为树
*/
export class BehaviorTreeStarter {
/**
* 启动行为树
*
* 给根节点添加 ActiveNode 组件,使行为树开始执行
*
* @param rootEntity 行为树根节点实体
*
* @example
* ```typescript
* const aiRoot = scene.createEntity('aiRoot');
* // ... 构建行为树结构
* BehaviorTreeStarter.start(aiRoot);
* ```
*/
static start(rootEntity: Entity): void {
if (!rootEntity.hasComponent(BehaviorTreeNode)) {
throw new Error('Entity must have BehaviorTreeNode component');
}
if (!rootEntity.hasComponent(ActiveNode)) {
rootEntity.addComponent(new ActiveNode());
}
}
/**
* 停止行为树
*
* 移除所有节点的 ActiveNode 组件,停止执行
*
* @param rootEntity 行为树根节点实体
*
* @example
* ```typescript
* BehaviorTreeStarter.stop(aiRoot);
* ```
*/
static stop(rootEntity: Entity): void {
this.stopRecursive(rootEntity);
}
/**
* 递归停止所有子节点
*/
private static stopRecursive(entity: Entity): void {
// 移除活跃标记
if (entity.hasComponent(ActiveNode)) {
entity.removeComponentByType(ActiveNode);
}
// 重置节点状态
const node = entity.getComponent(BehaviorTreeNode);
if (node) {
node.reset();
}
// 递归处理子节点
for (const child of entity.children) {
this.stopRecursive(child);
}
}
/**
* 暂停行为树
*
* 移除 ActiveNode 但保留节点状态,可以恢复执行
*
* @param rootEntity 行为树根节点实体
*
* @example
* ```typescript
* // 暂停
* BehaviorTreeStarter.pause(aiRoot);
*
* // 恢复
* BehaviorTreeStarter.resume(aiRoot);
* ```
*/
static pause(rootEntity: Entity): void {
this.pauseRecursive(rootEntity);
}
/**
* 递归暂停所有子节点
*/
private static pauseRecursive(entity: Entity): void {
// 只移除活跃标记,不重置状态
if (entity.hasComponent(ActiveNode)) {
entity.removeComponentByType(ActiveNode);
}
// 递归处理子节点
for (const child of entity.children) {
this.pauseRecursive(child);
}
}
/**
* 恢复行为树执行
*
* 从暂停状态恢复,重新添加 ActiveNode 到之前正在执行的节点
*
* @param rootEntity 行为树根节点实体
*
* @example
* ```typescript
* BehaviorTreeStarter.resume(aiRoot);
* ```
*/
static resume(rootEntity: Entity): void {
this.resumeRecursive(rootEntity);
}
/**
* 递归恢复所有正在执行的节点
*/
private static resumeRecursive(entity: Entity): void {
const node = entity.getComponent(BehaviorTreeNode);
if (!node) {
return;
}
// 如果节点状态是 Running恢复活跃标记
if (node.status === TaskStatus.Running) {
if (!entity.hasComponent(ActiveNode)) {
entity.addComponent(new ActiveNode());
}
}
// 递归处理子节点
for (const child of entity.children) {
this.resumeRecursive(child);
}
}
/**
* 重启行为树
*
* 停止并重置所有节点,然后重新启动
*
* @param rootEntity 行为树根节点实体
*
* @example
* ```typescript
* BehaviorTreeStarter.restart(aiRoot);
* ```
*/
static restart(rootEntity: Entity): void {
this.stop(rootEntity);
this.start(rootEntity);
}
/**
* 检查行为树是否正在运行
*
* @param rootEntity 行为树根节点实体
* @returns 是否正在运行
*
* @example
* ```typescript
* if (BehaviorTreeStarter.isRunning(aiRoot)) {
* console.log('AI is active');
* }
* ```
*/
static isRunning(rootEntity: Entity): boolean {
return rootEntity.hasComponent(ActiveNode);
}
}