Files
esengine/extensions/cocos/cocos-ecs/assets/scripts/ecs/systems/AISystem.ts
YHH bb19f752a1 优化性能结构/延迟加载
新增测试代码用于测试性能
2025-07-02 00:13:29 +08:00

317 lines
11 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { EntitySystem, Entity, Matcher, Time } from '@esengine/ecs-framework';
import { AIComponent, Transform, Health } from '../components';
/**
* AI系统 - 处理AI行为和状态机
*/
export class AISystem extends EntitySystem {
/** 系统处理的实体计数器 */
private processedEntityCount: number = 0;
/** 状态转换计数器 */
private stateTransitionCount: number = 0;
constructor() {
// 处理具有AI组件的实体
super(Matcher.empty().all(AIComponent));
}
/**
* 处理所有实体
*/
protected process(entities: Entity[]): void {
const deltaTime = Time.deltaTime;
const currentTime = Time.totalTime;
this.processedEntityCount = entities.length;
for (const entity of entities) {
this.processEntity(entity, deltaTime, currentTime);
}
// 批量处理AI间的交互
this.processAIInteractions(entities);
}
/**
* 处理单个实体
*/
private processEntity(entity: Entity, deltaTime: number, currentTime: number): void {
const ai = entity.getComponent(AIComponent);
const transform = entity.getComponent(Transform);
const health = entity.getComponent(Health);
if (!ai) return;
// 更新感知系统
ai.updatePerception(deltaTime);
// 处理状态机
this.updateStateMachine(ai, deltaTime);
// 更新行为树
this.updateBehaviorTree(ai, deltaTime);
// 处理AI能力如果有Transform和Health组件
if (transform && health) {
this.updateAICapabilities(ai, transform, health, deltaTime);
}
// 处理记忆衰减
this.updateMemory(ai, deltaTime);
}
/**
* 更新状态机
*/
private updateStateMachine(ai: AIComponent, deltaTime: number): void {
const currentStateName = ai.currentState;
const transitions = ai.stateMachine.transitions.get(currentStateName);
if (transitions) {
// 按优先级排序转换条件
const sortedTransitions = transitions.sort((a, b) => b.priority - a.priority);
for (const transition of sortedTransitions) {
if (transition.condition()) {
// 执行状态转换
const currentState = ai.stateMachine.states.get(currentStateName);
const newState = ai.stateMachine.states.get(transition.targetState);
if (currentState && newState) {
currentState.exit();
ai.currentState = transition.targetState as any;
newState.enter();
this.stateTransitionCount++;
break;
}
}
}
}
}
/**
* 更新行为树
*/
private updateBehaviorTree(ai: AIComponent, deltaTime: number): void {
const behaviorTree = ai.config.behaviorTree;
const blackboard = behaviorTree.blackboard;
// 更新黑板数据
blackboard.set('deltaTime', deltaTime);
blackboard.set('currentTime', Date.now());
// 模拟行为树执行
const executionResult = this.executeBehaviorNode(behaviorTree.rootNode, ai);
// 记录执行历史
behaviorTree.executionHistory.push({
nodeName: behaviorTree.rootNode.name,
startTime: Date.now(),
endTime: Date.now() + Math.random() * 10,
result: executionResult,
data: { deltaTime }
});
// 保持历史记录在合理范围内
if (behaviorTree.executionHistory.length > 50) {
behaviorTree.executionHistory.shift();
}
}
/**
* 执行行为树节点(模拟)
*/
private executeBehaviorNode(node: any, ai: AIComponent): 'success' | 'failure' | 'running' {
// 简单的行为树执行模拟
switch (node.name) {
case 'root':
case 'selector':
// 选择器节点:尝试执行子节点直到一个成功
for (const child of node.children) {
const result = this.executeBehaviorNode(child, ai);
if (result === 'success' || result === 'running') {
return result;
}
}
return 'failure';
case 'sequence':
// 序列节点:按顺序执行所有子节点
for (const child of node.children) {
const result = this.executeBehaviorNode(child, ai);
if (result === 'failure' || result === 'running') {
return result;
}
}
return 'success';
case 'condition':
// 条件节点检查AI状态
return ai.config.personality.intelligence > 0.5 ? 'success' : 'failure';
case 'action':
// 动作节点执行AI行为
return Math.random() > 0.3 ? 'success' : 'running';
default:
return 'failure';
}
}
/**
* 更新AI能力
*/
private updateAICapabilities(ai: AIComponent, transform: Transform, health: Health, deltaTime: number): void {
const capabilities = ai.config.capabilities;
// 根据健康状况调整能力
const healthRatio = health.currentHealth / health.maxHealth;
const effectiveSpeed = capabilities.movementSpeed * healthRatio;
// 更新移动速度
transform.speed = effectiveSpeed;
// 根据个性调整行为
if (ai.config.personality.aggression > 0.7 && healthRatio > 0.5) {
// 高攻击性且健康状况良好时更主动
ai.currentState = 'chase';
} else if (healthRatio < 0.3) {
// 生命值低时逃跑
ai.currentState = 'flee';
}
}
/**
* 更新记忆系统
*/
private updateMemory(ai: AIComponent, deltaTime: number): void {
const memory = ai.config.memory;
const currentTime = Date.now();
// 衰减已知位置的可信度
memory.knownLocations.forEach(location => {
const timeSinceVisit = currentTime - location.lastVisited;
const decayFactor = Math.exp(-timeSinceVisit / 30000); // 30秒衰减率
location.confidence *= decayFactor;
});
// 移除可信度过低的位置
memory.knownLocations = memory.knownLocations.filter(location => location.confidence > 0.1);
// 衰减关系信任度
memory.relationships.forEach(relation => {
const timeSinceInteraction = currentTime - relation.lastInteraction;
if (timeSinceInteraction > 60000) { // 60秒没有交互
relation.trustLevel *= 0.99; // 缓慢衰减
}
});
}
/**
* 处理AI间的交互
*/
private processAIInteractions(entities: Entity[]): void {
const aiEntities = entities.filter(e => e.getComponent(AIComponent));
for (let i = 0; i < aiEntities.length; i++) {
for (let j = i + 1; j < aiEntities.length; j++) {
this.processAIPair(aiEntities[i], aiEntities[j]);
}
}
}
/**
* 处理两个AI实体间的交互
*/
private processAIPair(entity1: Entity, entity2: Entity): void {
const ai1 = entity1.getComponent(AIComponent);
const ai2 = entity2.getComponent(AIComponent);
const transform1 = entity1.getComponent(Transform);
const transform2 = entity2.getComponent(Transform);
if (!ai1 || !ai2 || !transform1 || !transform2) return;
// 计算距离
const distance = Math.sqrt(
Math.pow(transform1.position.x - transform2.position.x, 2) +
Math.pow(transform1.position.y - transform2.position.y, 2)
);
// 视线范围内的交互
if (distance <= ai1.config.capabilities.sightRange) {
this.handleVisualContact(ai1, ai2, entity1, entity2, distance);
}
// 听力范围内的交互
if (distance <= ai1.config.capabilities.hearingRange) {
this.handleAudioContact(ai1, ai2, distance);
}
// 创建盟友关系(随机)
if (Math.random() < 0.001 && !ai1.allyIds.includes(entity2.id)) { // 0.1%概率每帧
ai1.addAlly(entity2.id);
}
}
/**
* 处理视觉接触
*/
private handleVisualContact(ai1: AIComponent, ai2: AIComponent, entity1: Entity, entity2: Entity, distance: number): void {
const currentTime = Date.now();
// 添加到可见实体列表
const existingEntry = ai1.perception.visibleEntities.find(e => e.entityId === entity2.id);
if (existingEntry) {
existingEntry.distance = distance;
existingEntry.lastSeen = currentTime;
existingEntry.componentId = ai2.id; // 使用组件ID避免循环引用
} else {
ai1.perception.visibleEntities.push({
entityId: entity2.id,
position: entity2.getComponent(Transform)!.position.clone(),
distance: distance,
angle: Math.atan2(
entity2.getComponent(Transform)!.position.y - entity1.getComponent(Transform)!.position.y,
entity2.getComponent(Transform)!.position.x - entity1.getComponent(Transform)!.position.x
),
lastSeen: currentTime,
componentId: ai2.id
});
}
}
/**
* 处理音频接触
*/
private handleAudioContact(ai1: AIComponent, ai2: AIComponent, distance: number): void {
const soundVolume = 1.0 - (distance / ai1.config.capabilities.hearingRange);
ai1.perception.audibleSounds.push({
source: ai2.entity.getComponent(Transform)!.position.clone(),
volume: soundVolume,
type: 'movement',
timestamp: Date.now()
});
}
/**
* 系统初始化时调用
*/
public initialize(): void {
super.initialize();
console.log('🤖 AI系统已启动');
}
/**
* 获取系统统计信息
*/
public getSystemStats(): any {
return {
processedEntities: this.processedEntityCount,
stateTransitions: this.stateTransitionCount,
systemName: 'AISystem'
};
}
}