优化性能结构/延迟加载

新增测试代码用于测试性能
This commit is contained in:
YHH
2025-07-02 00:13:29 +08:00
parent 6bd9c1055c
commit bb19f752a1
23 changed files with 3425 additions and 512 deletions

View File

@@ -42,11 +42,12 @@ export class ECSManager extends Component {
// 1. 创建Core实例启用调试功能
if (this.debugMode) {
Core.create({
debug: true,
enableEntitySystems: true,
debugConfig: {
enabled: true,
websocketUrl: 'ws://localhost:8080',
autoReconnect: true,
updateInterval: 100,
debugFrameRate: 30,
channels: {
entities: true,
@@ -57,9 +58,13 @@ export class ECSManager extends Component {
}
}
});
// ECS调试模式已启用
console.log('✅ ECS调试模式已启用');
} else {
Core.create(false);
Core.create({
debug: false,
enableEntitySystems: true
});
console.log(' ECS调试模式已禁用');
}
// 2. 创建游戏场景

View File

@@ -0,0 +1,328 @@
import { Component } from '@esengine/ecs-framework';
import { Vec3 } from 'cc';
/**
* AI组件 - 复杂的AI行为和状态管理
*/
export class AIComponent extends Component {
/** AI状态 */
public currentState: 'idle' | 'patrol' | 'chase' | 'attack' | 'flee' | 'dead' = 'idle';
/** 目标ID避免循环引用 */
public targetId: number | null = null;
/** AI伙伴ID列表避免循环引用 */
public allyIds: number[] = [];
/** 敌人ID列表 */
public enemyIds: number[] = [];
/** 复杂的AI配置 */
public config: {
personality: {
aggression: number; // 攻击性 0-1
curiosity: number; // 好奇心 0-1
loyalty: number; // 忠诚度 0-1
intelligence: number; // 智力 0-1
};
capabilities: {
sightRange: number;
hearingRange: number;
movementSpeed: number;
attackDamage: number;
health: number;
};
behaviorTree: {
rootNode: BehaviorNode;
blackboard: Map<string, any>;
executionHistory: BehaviorExecution[];
};
memory: {
lastSeenEnemyPosition: Vec3 | null;
lastSeenEnemyTime: number;
knownLocations: Array<{
position: Vec3;
type: 'safe' | 'danger' | 'resource' | 'patrol';
confidence: number;
lastVisited: number;
}>;
relationships: Map<number, {
entityId: number;
relationship: 'ally' | 'enemy' | 'neutral';
trustLevel: number;
lastInteraction: number;
interactionHistory: Array<{
type: 'friendly' | 'hostile' | 'neutral';
timestamp: number;
impact: number;
}>;
}>;
};
};
/** 状态机 */
public stateMachine: {
states: Map<string, AIState>;
transitions: Map<string, Array<{
targetState: string;
condition: () => boolean;
priority: number;
}>>;
stateHistory: Array<{
state: string;
enterTime: number;
exitTime: number;
data: any;
}>;
};
/** 感知系统 */
public perception: {
visibleEntities: Array<{
entityId: number;
position: Vec3;
distance: number;
angle: number;
lastSeen: number;
componentId?: number; // 使用组件ID避免循环引用
}>;
audibleSounds: Array<{
source: Vec3;
volume: number;
type: string;
timestamp: number;
}>;
tacticleInfo: Array<{
entityId: number;
contactPoint: Vec3;
force: number;
timestamp: number;
}>;
};
constructor() {
super();
// 初始化AI配置
this.config = {
personality: {
aggression: Math.random(),
curiosity: Math.random(),
loyalty: Math.random(),
intelligence: Math.random()
},
capabilities: {
sightRange: 100 + Math.random() * 100,
hearingRange: 50 + Math.random() * 50,
movementSpeed: 80 + Math.random() * 40,
attackDamage: 10 + Math.random() * 20,
health: 80 + Math.random() * 40
},
behaviorTree: {
rootNode: new BehaviorNode('root'),
blackboard: new Map(),
executionHistory: []
},
memory: {
lastSeenEnemyPosition: null,
lastSeenEnemyTime: 0,
knownLocations: [],
relationships: new Map()
}
};
// 初始化状态机
this.stateMachine = {
states: new Map(),
transitions: new Map(),
stateHistory: []
};
// 初始化感知系统
this.perception = {
visibleEntities: [],
audibleSounds: [],
tacticleInfo: []
};
this.initializeStateMachine();
this.initializeBehaviorTree();
}
/**
* 初始化状态机
*/
private initializeStateMachine(): void {
// 添加基本状态
this.stateMachine.states.set('idle', new AIState('idle', this));
this.stateMachine.states.set('patrol', new AIState('patrol', this));
this.stateMachine.states.set('chase', new AIState('chase', this));
this.stateMachine.states.set('attack', new AIState('attack', this));
this.stateMachine.states.set('flee', new AIState('flee', this));
// 设置状态转换
this.stateMachine.transitions.set('idle', [
{ targetState: 'patrol', condition: () => Math.random() > 0.8, priority: 1 },
{ targetState: 'chase', condition: () => this.perception.visibleEntities.length > 0, priority: 3 }
]);
this.stateMachine.transitions.set('patrol', [
{ targetState: 'idle', condition: () => Math.random() > 0.9, priority: 1 },
{ targetState: 'chase', condition: () => this.hasVisibleEnemies(), priority: 3 }
]);
}
/**
* 初始化行为树
*/
private initializeBehaviorTree(): void {
const root = this.config.behaviorTree.rootNode;
// 构建简单的行为树结构
const selectorNode = new BehaviorNode('selector');
const sequenceNode = new BehaviorNode('sequence');
const conditionNode = new BehaviorNode('condition');
const actionNode = new BehaviorNode('action');
root.addChild(selectorNode);
selectorNode.addChild(sequenceNode);
sequenceNode.addChild(conditionNode);
sequenceNode.addChild(actionNode);
// 设置黑板数据
this.config.behaviorTree.blackboard.set('lastPatrolPoint', new Vec3());
this.config.behaviorTree.blackboard.set('alertLevel', 0);
this.config.behaviorTree.blackboard.set('energy', 100);
}
/**
* 添加盟友(避免循环引用)
*/
public addAlly(allyEntityId: number): void {
if (!this.allyIds.includes(allyEntityId)) {
this.allyIds.push(allyEntityId);
// 更新关系记录
this.config.memory.relationships.set(allyEntityId, {
entityId: allyEntityId,
relationship: 'ally',
trustLevel: 0.8,
lastInteraction: Date.now(),
interactionHistory: []
});
}
}
/**
* 设置目标(避免循环引用)
*/
public setTarget(targetEntityId: number): void {
this.targetId = targetEntityId;
// 不再需要双向引用
}
/**
* 更新感知信息
*/
public updatePerception(deltaTime: number): void {
// 清理过期的感知信息
const currentTime = Date.now();
this.perception.visibleEntities = this.perception.visibleEntities.filter(
entity => currentTime - entity.lastSeen < 5000
);
this.perception.audibleSounds = this.perception.audibleSounds.filter(
sound => currentTime - sound.timestamp < 2000
);
// 更新记忆中的位置信息
this.config.memory.knownLocations.forEach(location => {
location.confidence *= 0.999; // 随时间衰减可信度
});
}
/**
* 检查是否有可见敌人
*/
private hasVisibleEnemies(): boolean {
return this.perception.visibleEntities.some(entity =>
this.config.memory.relationships.get(entity.entityId)?.relationship === 'enemy'
);
}
/**
* 重置组件
*/
public reset(): void {
// 清理ID数组不再需要处理循环引用
this.allyIds = [];
this.enemyIds = [];
this.targetId = null;
this.currentState = 'idle';
this.config.behaviorTree.blackboard.clear();
this.config.memory.relationships.clear();
this.perception.visibleEntities = [];
this.perception.audibleSounds = [];
this.perception.tacticleInfo = [];
}
}
/**
* 行为树节点
*/
class BehaviorNode {
public name: string;
public children: BehaviorNode[] = [];
public parent: BehaviorNode | null = null;
public data: Map<string, any> = new Map();
constructor(name: string) {
this.name = name;
}
public addChild(child: BehaviorNode): void {
this.children.push(child);
child.parent = this;
}
}
/**
* 行为执行记录
*/
interface BehaviorExecution {
nodeName: string;
startTime: number;
endTime: number;
result: 'success' | 'failure' | 'running';
data: any;
}
/**
* AI状态
*/
class AIState {
public name: string;
public owner: AIComponent;
public enterTime: number = 0;
public data: Map<string, any> = new Map();
constructor(name: string, owner: AIComponent) {
this.name = name;
this.owner = owner;
}
public enter(): void {
this.enterTime = Date.now();
}
public exit(): void {
// 记录状态历史
this.owner.stateMachine.stateHistory.push({
state: this.name,
enterTime: this.enterTime,
exitTime: Date.now(),
data: Object.fromEntries(this.data)
});
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "cc0d3d0d-0c12-4007-8568-11b2cafdfb8f",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,413 @@
import { Component } from '@esengine/ecs-framework';
/**
* 网络组件 - 模拟复杂的网络连接和数据同步(已移除循环引用)
*/
export class NetworkComponent extends Component {
/** 网络ID */
public networkId: string = '';
/** 连接状态 */
public connectionState: 'disconnected' | 'connecting' | 'connected' | 'error' = 'disconnected';
/** 网络连接信息 */
public connection: {
sessionId: string;
serverId: string;
roomId: string;
playerId: string;
ping: number;
packetLoss: number;
bandwidth: number;
lastHeartbeat: number;
};
/** 同步数据 */
public syncData: {
dirtyFlags: Set<string>;
lastSyncTime: number;
syncHistory: Array<{
timestamp: number;
dataSize: number;
properties: string[];
success: boolean;
}>;
queuedUpdates: Array<{
property: string;
value: any;
timestamp: number;
priority: number;
}>;
};
/** 网络统计 */
public networkStats: {
totalBytesSent: number;
totalBytesReceived: number;
packetsPerSecond: number;
averageLatency: number;
latencyHistory: number[];
connectionQuality: 'excellent' | 'good' | 'fair' | 'poor';
errorCount: number;
reconnectCount: number;
lastErrorTime: number;
errorLog: Array<{
timestamp: number;
errorType: string;
message: string;
stack?: string;
}>;
};
/** 连接的玩家ID列表避免循环引用 */
public connectedPlayerIds: Set<string> = new Set();
/** 群组成员ID避免循环引用 */
public groupMemberIds: string[] = [];
/** 群组领导者ID避免循环引用 */
public groupLeaderId: string | null = null;
/** 复杂的网络配置 */
public config: {
autoReconnect: boolean;
maxReconnectAttempts: number;
heartbeatInterval: number;
syncFrequency: number;
compressionEnabled: boolean;
encryptionEnabled: boolean;
priorityLevels: Map<string, number>;
filters: Array<{
property: string;
condition: (value: any) => boolean;
action: 'allow' | 'deny' | 'transform';
transformer?: (value: any) => any;
}>;
bufferSettings: {
maxBufferSize: number;
flushInterval: number;
compressionThreshold: number;
};
};
/** 消息队列 */
public messageQueue: {
incoming: Array<{
senderId: string;
messageType: string;
data: any;
timestamp: number;
processed: boolean;
}>;
outgoing: Array<{
targetId: string;
messageType: string;
data: any;
priority: number;
attempts: number;
maxAttempts: number;
}>;
processing: Map<string, {
messageId: string;
startTime: number;
expectedDuration: number;
status: 'processing' | 'completed' | 'failed';
}>;
};
/** 复杂的网络缓存系统 */
public cacheSystem: {
playerCache: Map<string, {
playerId: string;
lastSeen: number;
cachedData: any;
cacheExpiry: number;
}>;
messageCache: Map<string, {
messageId: string;
content: any;
timestamp: number;
recipients: string[];
}>;
syncCache: Map<string, {
propertyPath: string;
value: any;
lastUpdated: number;
version: number;
}>;
};
constructor(networkId: string = '') {
super();
this.networkId = networkId || this.generateNetworkId();
this.connection = {
sessionId: '',
serverId: '',
roomId: '',
playerId: '',
ping: 0,
packetLoss: 0,
bandwidth: 0,
lastHeartbeat: 0
};
this.syncData = {
dirtyFlags: new Set(),
lastSyncTime: 0,
syncHistory: [],
queuedUpdates: []
};
this.networkStats = {
totalBytesSent: 0,
totalBytesReceived: 0,
packetsPerSecond: 0,
averageLatency: 0,
latencyHistory: [],
connectionQuality: 'excellent',
errorCount: 0,
reconnectCount: 0,
lastErrorTime: 0,
errorLog: []
};
this.config = {
autoReconnect: true,
maxReconnectAttempts: 5,
heartbeatInterval: 1000,
syncFrequency: 60,
compressionEnabled: true,
encryptionEnabled: false,
priorityLevels: new Map([
['critical', 10],
['high', 7],
['medium', 5],
['low', 2]
]),
filters: [],
bufferSettings: {
maxBufferSize: 1024 * 1024, // 1MB
flushInterval: 100,
compressionThreshold: 1024
}
};
this.messageQueue = {
incoming: [],
outgoing: [],
processing: new Map()
};
this.cacheSystem = {
playerCache: new Map(),
messageCache: new Map(),
syncCache: new Map()
};
}
/**
* 生成网络ID
*/
private generateNetworkId(): string {
return 'net_' + Math.random().toString(36).substring(2, 15) +
Math.random().toString(36).substring(2, 15);
}
/**
* 连接到其他网络组件(避免循环引用)
*/
public connectToPlayer(playerNetworkId: string): void {
if (!this.connectedPlayerIds.has(playerNetworkId)) {
this.connectedPlayerIds.add(playerNetworkId);
// 记录连接事件
this.logNetworkEvent('player_connected', {
playerId: playerNetworkId,
timestamp: Date.now()
});
}
}
/**
* 加入群组(避免循环引用)
*/
public joinGroup(memberIds: string[], leaderId?: string): void {
this.groupMemberIds = [...memberIds];
this.groupLeaderId = leaderId || null;
// 更新缓存
memberIds.forEach(memberId => {
this.cacheSystem.playerCache.set(memberId, {
playerId: memberId,
lastSeen: Date.now(),
cachedData: {},
cacheExpiry: Date.now() + 300000 // 5分钟缓存
});
});
}
/**
* 发送消息
*/
public sendMessage(targetId: string, messageType: string, data: any, priority: number = 5): void {
const message = {
targetId,
messageType,
data: this.processOutgoingData(data),
priority,
attempts: 0,
maxAttempts: 3
};
this.messageQueue.outgoing.push(message);
this.messageQueue.outgoing.sort((a, b) => b.priority - a.priority);
// 更新统计
this.networkStats.totalBytesSent += JSON.stringify(data).length;
}
/**
* 处理传出数据
*/
private processOutgoingData(data: any): any {
let processedData = data;
// 应用过滤器
this.config.filters.forEach(filter => {
if (filter.condition(processedData)) {
if (filter.action === 'transform' && filter.transformer) {
processedData = filter.transformer(processedData);
}
}
});
// 压缩数据
if (this.config.compressionEnabled) {
processedData = this.compressData(processedData);
}
return processedData;
}
/**
* 压缩数据(模拟)
*/
private compressData(data: any): any {
// 模拟压缩算法
const serialized = JSON.stringify(data);
if (serialized.length > this.config.bufferSettings.compressionThreshold) {
// 模拟压缩
return {
compressed: true,
originalSize: serialized.length,
compressedSize: Math.floor(serialized.length * 0.6),
data: serialized.substring(0, Math.floor(serialized.length * 0.6))
};
}
return data;
}
/**
* 标记属性为脏
*/
public markDirty(property: string): void {
this.syncData.dirtyFlags.add(property);
}
/**
* 更新网络统计
*/
public updateNetworkStats(deltaTime: number): void {
// 更新延迟历史
if (this.networkStats.latencyHistory.length > 100) {
this.networkStats.latencyHistory.shift();
}
this.networkStats.latencyHistory.push(this.connection.ping);
// 计算平均延迟
this.networkStats.averageLatency = this.networkStats.latencyHistory.reduce((a, b) => a + b, 0) /
this.networkStats.latencyHistory.length;
// 更新连接质量
if (this.networkStats.averageLatency < 50) {
this.networkStats.connectionQuality = 'excellent';
} else if (this.networkStats.averageLatency < 100) {
this.networkStats.connectionQuality = 'good';
} else if (this.networkStats.averageLatency < 200) {
this.networkStats.connectionQuality = 'fair';
} else {
this.networkStats.connectionQuality = 'poor';
}
// 更新包率
this.networkStats.packetsPerSecond = this.messageQueue.outgoing.length / deltaTime;
// 清理过期缓存
this.cleanupExpiredCache();
}
/**
* 清理过期缓存
*/
private cleanupExpiredCache(): void {
const now = Date.now();
// 清理玩家缓存
for (const [key, value] of this.cacheSystem.playerCache) {
if (value.cacheExpiry < now) {
this.cacheSystem.playerCache.delete(key);
}
}
// 清理消息缓存
for (const [key, value] of this.cacheSystem.messageCache) {
if (value.timestamp < now - 600000) { // 10分钟过期
this.cacheSystem.messageCache.delete(key);
}
}
}
/**
* 记录网络事件
*/
private logNetworkEvent(eventType: string, data: any): void {
this.networkStats.errorLog.push({
timestamp: Date.now(),
errorType: eventType,
message: JSON.stringify(data)
});
// 限制日志大小
if (this.networkStats.errorLog.length > 1000) {
this.networkStats.errorLog = this.networkStats.errorLog.slice(-500);
}
}
/**
* 重置组件
*/
public reset(): void {
// 清理ID列表不再需要处理循环引用
this.connectedPlayerIds.clear();
this.groupMemberIds = [];
this.groupLeaderId = null;
this.connectionState = 'disconnected';
this.syncData.dirtyFlags.clear();
this.syncData.syncHistory = [];
this.syncData.queuedUpdates = [];
this.messageQueue.incoming = [];
this.messageQueue.outgoing = [];
this.messageQueue.processing.clear();
this.cacheSystem.playerCache.clear();
this.cacheSystem.messageCache.clear();
this.cacheSystem.syncCache.clear();
this.networkStats.errorLog = [];
this.networkStats.latencyHistory = [];
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "d9263549-7b26-4b4f-9a15-b82e7af5fbd5",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,346 @@
import { Component } from '@esengine/ecs-framework';
import { Node, Vec3, Color, Sprite, Label } from 'cc';
/**
* Node组件 - 包含Cocos Creator节点引用已移除循环引用
*/
export class NodeComponent extends Component {
/** Cocos Creator节点引用 */
public node: Node | null = null;
/** 子节点列表 */
public children: Node[] = [];
/** 节点配置信息 */
public nodeConfig: {
name: string;
layer: number;
tag: string;
userData: Record<string, any>;
transformData: {
position: Vec3;
rotation: Vec3;
scale: Vec3;
};
renderData: {
color: Color;
opacity: number;
visible: boolean;
};
parentId: number | null; // 避免循环引用使用父节点实体ID
childIds: number[]; // 避免循环引用使用子节点实体ID列表
};
/** 渲染组件引用 */
public sprite: Sprite | null = null;
public label: Label | null = null;
/** 复杂嵌套对象 */
public complexData: {
statistics: {
frameCount: number;
lastUpdateTime: number;
performance: {
avgRenderTime: number;
maxRenderTime: number;
renderHistory: number[];
};
};
cache: {
textureCache: Map<string, any>;
materialCache: Map<string, any>;
shaderCache: Map<string, any>;
};
hierarchy: {
parentId: number | null; // 避免循环引用使用ID
rootId: number | null; // 避免循环引用使用ID
depth: number;
siblingIndex: number;
};
animation: {
isPlaying: boolean;
currentFrame: number;
totalFrames: number;
loopCount: number;
animationQueue: Array<{
name: string;
duration: number;
delay: number;
easing: string;
}>;
};
interaction: {
isInteractable: boolean;
touchEnabled: boolean;
hitTestResults: Array<{
position: Vec3;
timestamp: number;
result: boolean;
}>;
boundingBox: {
min: Vec3;
max: Vec3;
center: Vec3;
};
};
};
/** 复杂的渲染状态 */
public renderState: {
layerInfo: {
currentLayer: number;
layerStack: number[];
sortingOrder: number;
cullingMask: number;
};
materials: Array<{
materialId: string;
properties: Map<string, any>;
textures: Map<string, any>;
shaderParams: Record<string, any>;
}>;
lightingData: {
ambientColor: Color;
diffuseColor: Color;
specularColor: Color;
lightDirection: Vec3;
shadowData: {
castShadows: boolean;
receiveShadows: boolean;
shadowQuality: 'low' | 'medium' | 'high';
shadowDistance: number;
};
};
};
constructor(name: string = "DefaultNode") {
super();
this.nodeConfig = {
name: name,
layer: 0,
tag: "default",
userData: {},
transformData: {
position: new Vec3(),
rotation: new Vec3(),
scale: new Vec3(1, 1, 1)
},
renderData: {
color: new Color(255, 255, 255, 255),
opacity: 1.0,
visible: true
},
parentId: null,
childIds: []
};
this.complexData = {
statistics: {
frameCount: 0,
lastUpdateTime: 0,
performance: {
avgRenderTime: 0,
maxRenderTime: 0,
renderHistory: []
}
},
cache: {
textureCache: new Map(),
materialCache: new Map(),
shaderCache: new Map()
},
hierarchy: {
parentId: null,
rootId: null,
depth: 0,
siblingIndex: 0
},
animation: {
isPlaying: false,
currentFrame: 0,
totalFrames: 60,
loopCount: 0,
animationQueue: []
},
interaction: {
isInteractable: true,
touchEnabled: true,
hitTestResults: [],
boundingBox: {
min: new Vec3(-1, -1, -1),
max: new Vec3(1, 1, 1),
center: new Vec3()
}
}
};
this.renderState = {
layerInfo: {
currentLayer: 0,
layerStack: [0],
sortingOrder: 0,
cullingMask: 0xFFFFFFFF
},
materials: [],
lightingData: {
ambientColor: new Color(128, 128, 128, 255),
diffuseColor: new Color(255, 255, 255, 255),
specularColor: new Color(255, 255, 255, 255),
lightDirection: new Vec3(0, -1, 0),
shadowData: {
castShadows: true,
receiveShadows: true,
shadowQuality: 'medium',
shadowDistance: 100
}
}
};
}
/**
* 设置父节点组件(避免循环引用)
*/
public setParent(parentEntityId: number): void {
this.nodeConfig.parentId = parentEntityId;
this.complexData.hierarchy.parentId = parentEntityId;
// 深度需要通过其他方式计算,避免引用
}
/**
* 添加子节点
*/
public addChild(childEntityId: number): void {
if (!this.nodeConfig.childIds.includes(childEntityId)) {
this.nodeConfig.childIds.push(childEntityId);
}
}
/**
* 更新性能统计
*/
public updatePerformance(renderTime: number): void {
this.complexData.statistics.frameCount++;
this.complexData.statistics.lastUpdateTime = Date.now();
const perf = this.complexData.statistics.performance;
perf.renderHistory.push(renderTime);
// 保持历史记录在合理范围内
if (perf.renderHistory.length > 100) {
perf.renderHistory.shift();
}
// 计算平均值和最大值
perf.avgRenderTime = perf.renderHistory.reduce((a, b) => a + b, 0) / perf.renderHistory.length;
perf.maxRenderTime = Math.max(perf.maxRenderTime, renderTime);
}
/**
* 更新动画状态
*/
public updateAnimation(deltaTime: number): void {
if (this.complexData.animation.isPlaying) {
this.complexData.animation.currentFrame++;
if (this.complexData.animation.currentFrame >= this.complexData.animation.totalFrames) {
this.complexData.animation.currentFrame = 0;
this.complexData.animation.loopCount++;
// 处理动画队列
if (this.complexData.animation.animationQueue.length > 0) {
const nextAnim = this.complexData.animation.animationQueue.shift();
if (nextAnim) {
this.complexData.animation.totalFrames = Math.floor(nextAnim.duration * 60); // 假设60FPS
}
}
}
}
}
/**
* 添加材质
*/
public addMaterial(materialId: string, properties: Record<string, any>): void {
this.renderState.materials.push({
materialId,
properties: new Map(Object.entries(properties)),
textures: new Map(),
shaderParams: {}
});
}
/**
* 更新包围盒
*/
public updateBoundingBox(): void {
if (this.node) {
const worldPos = this.node.getWorldPosition();
const scale = this.node.getScale();
this.complexData.interaction.boundingBox.center = new Vec3(worldPos.x, worldPos.y, worldPos.z);
this.complexData.interaction.boundingBox.min = new Vec3(
worldPos.x - scale.x * 0.5,
worldPos.y - scale.y * 0.5,
worldPos.z - scale.z * 0.5
);
this.complexData.interaction.boundingBox.max = new Vec3(
worldPos.x + scale.x * 0.5,
worldPos.y + scale.y * 0.5,
worldPos.z + scale.z * 0.5
);
}
}
/**
* 执行点击测试
*/
public hitTest(point: Vec3): boolean {
const bbox = this.complexData.interaction.boundingBox;
const result = point.x >= bbox.min.x && point.x <= bbox.max.x &&
point.y >= bbox.min.y && point.y <= bbox.max.y &&
point.z >= bbox.min.z && point.z <= bbox.max.z;
// 记录测试结果
this.complexData.interaction.hitTestResults.push({
position: new Vec3(point.x, point.y, point.z),
timestamp: Date.now(),
result
});
// 限制历史记录大小
if (this.complexData.interaction.hitTestResults.length > 50) {
this.complexData.interaction.hitTestResults.shift();
}
return result;
}
/**
* 重置组件
*/
public reset(): void {
this.node = null;
this.children = [];
this.sprite = null;
this.label = null;
// 清理ID列表不再需要处理循环引用
this.nodeConfig.parentId = null;
this.nodeConfig.childIds = [];
this.complexData.hierarchy.parentId = null;
this.complexData.hierarchy.rootId = null;
this.complexData.hierarchy.depth = 0;
this.complexData.cache.textureCache.clear();
this.complexData.cache.materialCache.clear();
this.complexData.cache.shaderCache.clear();
this.complexData.animation.isPlaying = false;
this.complexData.animation.currentFrame = 0;
this.complexData.animation.animationQueue = [];
this.complexData.interaction.hitTestResults = [];
this.renderState.materials = [];
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "28e7e8cd-591e-4fde-bb14-d668724a6201",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -2,4 +2,7 @@
export { Transform } from './Transform';
export { Health } from './Health';
export { Velocity } from './Velocity';
export { Renderer } from './Renderer';
export { Renderer } from './Renderer';
export { NodeComponent } from './NodeComponent';
export { AIComponent } from './AIComponent';
export { NetworkComponent } from './NetworkComponent';

View File

@@ -1,7 +1,7 @@
import { Scene } from '@esengine/ecs-framework';
import { Color } from 'cc';
import { MovementSystem, HealthSystem, RandomMovementSystem } from '../systems';
import { Transform, Health, Velocity, Renderer } from '../components';
import { Color, Node } from 'cc';
import { MovementSystem, HealthSystem, RandomMovementSystem, AISystem, NetworkSystem, NodeRenderSystem } from '../systems';
import { Transform, Health, Velocity, Renderer, NodeComponent, AIComponent, NetworkComponent } from '../components';
/**
* 游戏场景
@@ -29,77 +29,268 @@ export class GameScene extends Scene {
this.addEntityProcessor(new MovementSystem());
this.addEntityProcessor(new HealthSystem());
this.addEntityProcessor(new RandomMovementSystem());
// this.addEntityProcessor(new AISystem());
// this.addEntityProcessor(new NetworkSystem());
// this.addEntityProcessor(new NodeRenderSystem());
// 创建测试实体
this.createTestEntities();
// 创建大量复杂的测试实体
this.createComplexTestEntities();
}
/**
* 创建测试实体
* 创建复杂的测试实体1000+个)
*/
private createTestEntities(): void {
console.log('🚀 开始创建测试实体...');
private createComplexTestEntities(): void {
console.log('🚀 开始创建大量复杂测试实体...');
// 创建玩家实体
const player = this.createEntity("Player");
player.addComponent(new Transform());
player.addComponent(new Health(150));
player.addComponent(new Velocity());
player.addComponent(new Renderer("player", new Color(0, 255, 0, 255)));
// 存储创建的AI和网络组件用于建立循环引用
const aiComponents: AIComponent[] = [];
const networkComponents: NetworkComponent[] = [];
const nodeComponents: NodeComponent[] = [];
const playerTransform = player.getComponent(Transform);
const playerHealth = player.getComponent(Health);
if (playerTransform) {
playerTransform.setPosition(0, 0);
playerTransform.speed = 120;
}
if (playerHealth) {
playerHealth.regenRate = 5; // 每秒回复5点生命值
}
// 创建一些敌人实体
for (let i = 0; i < 10; i++) {
const enemy = this.createEntity(`Enemy_${i}`);
enemy.addComponent(new Transform());
enemy.addComponent(new Health(80));
enemy.addComponent(new Velocity());
enemy.addComponent(new Renderer("enemy", new Color(255, 0, 0, 255)));
// 1. 创建玩家实体(具有所有组件类型)
console.log('创建玩家实体...');
const player = this.createComplexEntity("Player", "player", new Color(0, 255, 0, 255), 0, 0, true, true, true);
if (player) {
const playerAI = player.getComponent(AIComponent);
const playerNetwork = player.getComponent(NetworkComponent);
const playerNode = player.getComponent(NodeComponent);
const enemyTransform = enemy.getComponent(Transform);
const enemyVelocity = enemy.getComponent(Velocity);
if (enemyTransform) {
// 随机位置
const x = (Math.random() - 0.5) * 800;
const y = (Math.random() - 0.5) * 600;
enemyTransform.setPosition(x, y);
enemyTransform.speed = 80;
}
if (enemyVelocity) {
enemyVelocity.maxSpeed = 120;
enemyVelocity.friction = 0.95;
if (playerAI) aiComponents.push(playerAI);
if (playerNetwork) networkComponents.push(playerNetwork);
if (playerNode) nodeComponents.push(playerNode);
}
// 2. 创建AI智能体500个
console.log('创建AI智能体...');
for (let i = 0; i < 500; i++) {
const entityName = `AI_Agent_${i}`;
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const color = new Color(
Math.floor(Math.random() * 255),
Math.floor(Math.random() * 255),
Math.floor(Math.random() * 255),
255
);
const entity = this.createComplexEntity(entityName, "ai_agent", color, x, y, true, true, Math.random() > 0.5);
if (entity) {
const ai = entity.getComponent(AIComponent);
const network = entity.getComponent(NetworkComponent);
const node = entity.getComponent(NodeComponent);
if (ai) {
aiComponents.push(ai);
// 设置随机AI个性
ai.config.personality.aggression = Math.random();
ai.config.personality.curiosity = Math.random();
ai.config.personality.loyalty = Math.random();
ai.config.personality.intelligence = Math.random();
}
if (network) {
networkComponents.push(network);
// 随机设置网络状态
if (Math.random() > 0.2) {
network.connectionState = 'connected';
}
}
if (node) {
nodeComponents.push(node);
// 设置随机节点属性
node.nodeConfig.layer = Math.floor(Math.random() * 10);
node.nodeConfig.tag = `layer_${node.nodeConfig.layer}`;
}
}
}
// 创建一些中性实体(只移动,无生命值
for (let i = 0; i < 5; i++) {
const neutral = this.createEntity(`Neutral_${i}`);
neutral.addComponent(new Transform());
neutral.addComponent(new Velocity());
neutral.addComponent(new Renderer("neutral", new Color(255, 255, 0, 255)));
// 3. 创建网络节点300个
console.log('创建网络节点...');
for (let i = 0; i < 300; i++) {
const entityName = `Network_Node_${i}`;
const x = (Math.random() - 0.5) * 1500;
const y = (Math.random() - 0.5) * 1500;
const color = new Color(0, 150, 255, 200);
const neutralTransform = neutral.getComponent(Transform);
const neutralVelocity = neutral.getComponent(Velocity);
if (neutralTransform) {
const x = (Math.random() - 0.5) * 600;
const y = (Math.random() - 0.5) * 400;
neutralTransform.setPosition(x, y);
neutralTransform.speed = 60;
}
if (neutralVelocity) {
neutralVelocity.maxSpeed = 80;
neutralVelocity.friction = 0.99;
const entity = this.createComplexEntity(entityName, "network_node", color, x, y, false, true, true);
if (entity) {
const network = entity.getComponent(NetworkComponent);
const node = entity.getComponent(NodeComponent);
if (network) {
networkComponents.push(network);
network.connectionState = 'connected';
network.config.syncFrequency = 30 + Math.random() * 30; // 30-60Hz
}
if (node) {
nodeComponents.push(node);
// 创建复杂的层次结构
node.nodeConfig.layer = Math.floor(i / 10); // 每10个一层
}
}
}
// 4. 创建简单移动实体200个
console.log('创建简单移动实体...');
for (let i = 0; i < 200; i++) {
const entityName = `Simple_Mover_${i}`;
const x = (Math.random() - 0.5) * 1000;
const y = (Math.random() - 0.5) * 1000;
const color = new Color(255, 255, 255, 150);
this.createComplexEntity(entityName, "simple_mover", color, x, y, false, false, false);
}
// 5. 建立循环引用和复杂关系
console.log('建立实体间的复杂关系...');
this.establishComplexRelationships(aiComponents, networkComponents, nodeComponents);
const totalEntities = this.entities.count;
console.log(`✅ 创建完成!总共创建了 ${totalEntities} 个实体`);
console.log(` - AI组件: ${aiComponents.length}`);
console.log(` - 网络组件: ${networkComponents.length}`);
console.log(` - 节点组件: ${nodeComponents.length}`);
}
/**
* 创建复杂实体的辅助方法
*/
private createComplexEntity(
name: string,
type: string,
color: Color,
x: number,
y: number,
hasAI: boolean,
hasNetwork: boolean,
hasNode: boolean
): any {
const entity = this.createEntity(name);
// 基础组件
const transform = new Transform();
transform.setPosition(x, y);
transform.speed = 50 + Math.random() * 100;
entity.addComponent(transform);
const health = new Health(50 + Math.random() * 100);
health.regenRate = Math.random() * 10;
entity.addComponent(health);
const velocity = new Velocity();
velocity.maxSpeed = 80 + Math.random() * 120;
velocity.friction = 0.95 + Math.random() * 0.04;
entity.addComponent(velocity);
const renderer = new Renderer(type, color.clone());
renderer.alpha = 0.5 + Math.random() * 0.5;
renderer.layer = Math.floor(Math.random() * 5);
entity.addComponent(renderer);
// 复杂组件
if (hasAI) {
const ai = new AIComponent();
entity.addComponent(ai);
}
if (hasNetwork) {
const network = new NetworkComponent(`${type}_${name}`);
entity.addComponent(network);
}
if (hasNode) {
const node = new NodeComponent(name);
entity.addComponent(node);
}
return entity;
}
/**
* 建立实体间的复杂关系
*/
private establishComplexRelationships(
aiComponents: AIComponent[],
networkComponents: NetworkComponent[],
nodeComponents: NodeComponent[]
): void {
// 建立AI之间的盟友/敌人关系(避免循环引用)
for (let i = 0; i < Math.min(aiComponents.length, 100); i++) {
const ai = aiComponents[i];
// 随机添加盟友使用实体ID
const allyCount = Math.floor(Math.random() * 5);
for (let j = 0; j < allyCount; j++) {
const randomIndex = Math.floor(Math.random() * aiComponents.length);
const ally = aiComponents[randomIndex];
if (ally !== ai && !ai.allyIds.includes(ally.entity.id)) {
ai.addAlly(ally.entity.id);
}
}
// 随机设置目标使用实体ID
if (Math.random() > 0.7) {
const randomIndex = Math.floor(Math.random() * aiComponents.length);
const target = aiComponents[randomIndex];
if (target !== ai) {
ai.setTarget(target.entity.id);
}
}
}
// 建立网络连接(避免循环引用)
for (let i = 0; i < Math.min(networkComponents.length, 50); i++) {
const network = networkComponents[i];
// 连接到其他网络组件使用网络ID
const connectionCount = Math.floor(Math.random() * 8);
for (let j = 0; j < connectionCount; j++) {
const randomIndex = Math.floor(Math.random() * networkComponents.length);
const other = networkComponents[randomIndex];
if (other !== network) {
network.connectToPlayer(other.networkId);
}
}
// 创建群组使用网络ID
if (Math.random() > 0.8) {
const groupSize = Math.floor(Math.random() * 10) + 2;
const groupMemberIds: string[] = [network.networkId];
for (let k = 0; k < groupSize - 1; k++) {
const randomIndex = Math.floor(Math.random() * networkComponents.length);
const member = networkComponents[randomIndex];
if (!groupMemberIds.includes(member.networkId)) {
groupMemberIds.push(member.networkId);
}
}
network.joinGroup(groupMemberIds, network.networkId);
}
}
// 建立节点层次结构(避免循环引用)
for (let i = 0; i < Math.min(nodeComponents.length, 30); i++) {
const parent = nodeComponents[i];
// 添加一些子节点使用实体ID
const childCount = Math.floor(Math.random() * 5);
for (let j = 0; j < childCount; j++) {
const childIndex = Math.floor(Math.random() * nodeComponents.length);
const child = nodeComponents[childIndex];
if (child !== parent && !parent.nodeConfig.childIds.includes(child.entity.id)) {
parent.addChild(child.entity.id);
}
}
}
console.log('🔗 复杂关系建立完成!');
}
/**

View File

@@ -0,0 +1,317 @@
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'
};
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "449fa887-eece-424d-ae1d-7082454fac3f",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,448 @@
import { EntitySystem, Entity, Matcher, Time } from '@esengine/ecs-framework';
import { NetworkComponent } from '../components';
/**
* 网络系统 - 处理网络同步和连接管理
*/
export class NetworkSystem extends EntitySystem {
/** 网络统计 */
private networkStats = {
totalEntities: 0,
connectedEntities: 0,
totalMessagesSent: 0,
totalMessagesReceived: 0,
averagePing: 0,
networkTraffic: 0
};
/** 消息处理队列 */
private globalMessageQueue: Array<{
from: string;
to: string;
messageType: string;
data: any;
timestamp: number;
priority: number;
}> = [];
constructor() {
// 处理具有网络组件的实体
super(Matcher.empty().all(NetworkComponent));
}
/**
* 处理所有实体
*/
protected process(entities: Entity[]): void {
const deltaTime = Time.deltaTime;
this.networkStats.totalEntities = entities.length;
this.networkStats.connectedEntities = entities.filter(e =>
e.getComponent(NetworkComponent)?.connectionState === 'connected'
).length;
for (const entity of entities) {
this.processEntity(entity, deltaTime);
}
// 处理全局消息队列
this.processGlobalMessages();
// 更新网络统计
this.updateGlobalNetworkStats(entities);
}
/**
* 处理单个实体
*/
private processEntity(entity: Entity, deltaTime: number): void {
const network = entity.getComponent(NetworkComponent);
if (!network) return;
// 更新网络统计
network.updateNetworkStats(deltaTime);
// 处理连接状态
this.updateConnectionState(network, deltaTime);
// 处理消息队列
this.processEntityMessages(network, entity);
// 处理数据同步
this.processSynchronization(network, deltaTime);
// 处理群组通信
this.processGroupCommunication(network);
}
/**
* 更新连接状态
*/
private updateConnectionState(network: NetworkComponent, deltaTime: number): void {
const currentTime = Date.now();
switch (network.connectionState) {
case 'disconnected':
// 尝试连接
if (network.config.autoReconnect &&
network.networkStats.reconnectCount < network.config.maxReconnectAttempts) {
network.connectionState = 'connecting';
network.connection.lastHeartbeat = currentTime;
}
break;
case 'connecting':
// 模拟连接过程
if (Math.random() > 0.1) { // 90% 成功率
network.connectionState = 'connected';
network.connection.sessionId = this.generateSessionId();
network.connection.serverId = 'server_001';
network.connection.lastHeartbeat = currentTime;
} else if (currentTime - network.connection.lastHeartbeat > 5000) {
// 连接超时
network.connectionState = 'error';
network.networkStats.errorCount++;
}
break;
case 'connected':
// 维持连接心跳
if (currentTime - network.connection.lastHeartbeat > network.config.heartbeatInterval) {
this.sendHeartbeat(network);
network.connection.lastHeartbeat = currentTime;
}
// 模拟网络质量变化
network.connection.ping = Math.random() * 100 + 20; // 20-120ms
network.connection.packetLoss = Math.random() * 0.05; // 0-5%
network.connection.bandwidth = 1000 + Math.random() * 500; // 1000-1500 Kbps
break;
case 'error':
// 错误状态,尝试重连
if (network.config.autoReconnect &&
network.networkStats.reconnectCount < network.config.maxReconnectAttempts) {
network.connectionState = 'disconnected';
network.networkStats.reconnectCount++;
}
break;
}
}
/**
* 处理实体消息
*/
private processEntityMessages(network: NetworkComponent, entity: Entity): void {
// 处理传出消息
const outgoingMessages = network.messageQueue.outgoing.slice();
network.messageQueue.outgoing = [];
for (const message of outgoingMessages) {
if (this.sendMessage(network, message)) {
this.networkStats.totalMessagesSent++;
network.networkStats.totalBytesSent += this.estimateMessageSize(message);
} else {
// 发送失败,重新加入队列
message.attempts++;
if (message.attempts < message.maxAttempts) {
network.messageQueue.outgoing.push(message);
}
}
}
// 处理传入消息
this.processIncomingMessages(network, entity);
}
/**
* 发送消息
*/
private sendMessage(network: NetworkComponent, message: any): boolean {
if (network.connectionState !== 'connected') {
return false;
}
// 模拟网络延迟和丢包
const shouldDelay = Math.random() < 0.3; // 30% 概率有延迟
const shouldDrop = Math.random() < network.connection.packetLoss;
if (shouldDrop) {
network.networkStats.errorCount++;
return false;
}
// 添加到全局消息队列
this.globalMessageQueue.push({
from: network.networkId,
to: message.targetId,
messageType: message.messageType,
data: message.data,
timestamp: Date.now() + (shouldDelay ? Math.random() * 200 : 0),
priority: message.priority
});
return true;
}
/**
* 处理传入消息
*/
private processIncomingMessages(network: NetworkComponent, entity: Entity): void {
// 从全局队列中获取发给此实体的消息
const incomingMessages = this.globalMessageQueue.filter(msg =>
msg.to === network.networkId && msg.timestamp <= Date.now()
);
// 从全局队列中移除这些消息
this.globalMessageQueue = this.globalMessageQueue.filter(msg =>
!(msg.to === network.networkId && msg.timestamp <= Date.now())
);
// 处理消息
for (const message of incomingMessages) {
network.messageQueue.incoming.push({
senderId: message.from,
messageType: message.messageType,
data: message.data,
timestamp: message.timestamp,
processed: false
});
this.networkStats.totalMessagesReceived++;
network.networkStats.totalBytesReceived += this.estimateMessageSize(message);
// 立即处理某些类型的消息
this.handleSpecialMessages(network, message);
}
}
/**
* 处理特殊消息类型
*/
private handleSpecialMessages(network: NetworkComponent, message: any): void {
switch (message.messageType) {
case 'player_join_group':
// 处理加入群组消息
const groupData = message.data;
if (groupData.members && Array.isArray(groupData.members)) {
// 查找对应的网络组件并建立连接
groupData.members.forEach((memberId: string) => {
// 直接使用成员ID建立连接
network.connectToPlayer(memberId);
});
}
break;
case 'heartbeat':
// 心跳响应
network.connection.ping = Date.now() - message.data.timestamp;
break;
case 'sync_request':
// 同步请求
this.handleSyncRequest(network, message);
break;
}
}
/**
* 处理数据同步
*/
private processSynchronization(network: NetworkComponent, deltaTime: number): void {
const currentTime = Date.now();
const syncInterval = 1000 / network.config.syncFrequency; // 转换为毫秒
if (currentTime - network.syncData.lastSyncTime >= syncInterval) {
this.performSynchronization(network);
network.syncData.lastSyncTime = currentTime;
}
// 处理排队的更新
this.processQueuedUpdates(network);
}
/**
* 执行同步
*/
private performSynchronization(network: NetworkComponent): void {
if (network.syncData.dirtyFlags.size === 0) {
return; // 没有需要同步的数据
}
const syncData = {
networkId: network.networkId,
timestamp: Date.now(),
properties: Array.from(network.syncData.dirtyFlags),
checksum: this.calculateChecksum(network)
};
// 发送同步数据给连接的玩家
network.connectedPlayerIds.forEach(playerId => {
network.sendMessage(playerId, 'sync_data', syncData, 7);
});
// 记录同步历史
network.syncData.syncHistory.push({
timestamp: syncData.timestamp,
dataSize: this.estimateMessageSize(syncData),
properties: syncData.properties,
success: true
});
// 清理脏标记
network.syncData.dirtyFlags.clear();
}
/**
* 处理排队的更新
*/
private processQueuedUpdates(network: NetworkComponent): void {
// 按优先级和时间戳排序
network.syncData.queuedUpdates.sort((a, b) => {
if (a.priority !== b.priority) {
return b.priority - a.priority; // 高优先级优先
}
return a.timestamp - b.timestamp; // 时间戳早的优先
});
// 处理前10个更新
const updatesToProcess = network.syncData.queuedUpdates.splice(0, 10);
for (const update of updatesToProcess) {
network.markDirty(update.property);
}
}
/**
* 处理群组通信
*/
private processGroupCommunication(network: NetworkComponent): void {
if (network.groupMemberIds.length === 0) {
return;
}
// 群组消息广播
if (Math.random() < 0.01) { // 1% 概率发送群组消息
const groupMessage = {
type: 'group_update',
data: {
sender: network.networkId,
timestamp: Date.now(),
groupSize: network.groupMemberIds.length,
status: network.connectionState
}
};
network.groupMemberIds.forEach(memberId => {
if (memberId !== network.networkId) {
network.sendMessage(memberId, 'group_message', groupMessage, 5);
}
});
}
}
/**
* 处理全局消息
*/
private processGlobalMessages(): void {
// 移除过期消息
const currentTime = Date.now();
this.globalMessageQueue = this.globalMessageQueue.filter(msg =>
currentTime - msg.timestamp < 30000 // 30秒过期
);
// 按优先级排序
this.globalMessageQueue.sort((a, b) => b.priority - a.priority);
}
/**
* 更新全局网络统计
*/
private updateGlobalNetworkStats(entities: Entity[]): void {
let totalPing = 0;
let connectedCount = 0;
let totalTraffic = 0;
for (const entity of entities) {
const network = entity.getComponent(NetworkComponent);
if (network && network.connectionState === 'connected') {
totalPing += network.connection.ping;
connectedCount++;
totalTraffic += network.networkStats.totalBytesSent + network.networkStats.totalBytesReceived;
}
}
this.networkStats.averagePing = connectedCount > 0 ? totalPing / connectedCount : 0;
this.networkStats.networkTraffic = totalTraffic;
}
/**
* 辅助方法
*/
private generateSessionId(): string {
return 'session_' + Math.random().toString(36).substring(2, 15);
}
private estimateMessageSize(message: any): number {
return JSON.stringify(message).length;
}
private calculateChecksum(network: NetworkComponent): string {
// 简单的校验和计算
const data = JSON.stringify({
networkId: network.networkId,
connectionState: network.connectionState
});
return btoa(data).substring(0, 8);
}
private sendHeartbeat(network: NetworkComponent): void {
network.sendMessage('server', 'heartbeat', { timestamp: Date.now() }, 10);
}
private findNetworkComponentById(networkId: string): NetworkComponent | null {
// 这里应该有一个全局的网络组件注册表
// 为了简化我们返回null
return null;
}
private handleSyncRequest(network: NetworkComponent, message: any): void {
// 处理同步请求
const response = {
requestId: message.data.requestId,
data: this.gatherSyncData(network),
timestamp: Date.now()
};
network.sendMessage(message.from, 'sync_response', response, 8);
}
private gatherSyncData(network: NetworkComponent): any {
return {
networkId: network.networkId,
connectionState: network.connectionState,
ping: network.connection.ping,
groupSize: network.groupMemberIds.length
};
}
/**
* 系统初始化时调用
*/
public initialize(): void {
super.initialize();
console.log('🌐 网络系统已启动');
}
/**
* 获取系统统计信息
*/
public getSystemStats(): any {
return {
...this.networkStats,
globalMessageQueueSize: this.globalMessageQueue.length,
systemName: 'NetworkSystem'
};
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "09cb67c9-12ef-48e0-949d-c8edf2c7ae22",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,475 @@
import { EntitySystem, Entity, Matcher, Time } from '@esengine/ecs-framework';
import { NodeComponent, Transform, Renderer } from '../components';
import { Node, Vec3, Color } from 'cc';
/**
* 节点渲染系统 - 处理NodeComponent和Cocos Creator节点的同步
*/
export class NodeRenderSystem extends EntitySystem {
/** 渲染统计 */
private renderStats = {
totalNodes: 0,
visibleNodes: 0,
renderCalls: 0,
averageRenderTime: 0,
totalRenderTime: 0,
frameCount: 0
};
/** 节点池 */
private nodePool: Node[] = [];
/** 性能监控 */
private performanceMonitor = {
frameStartTime: 0,
renderTimeHistory: [] as number[],
cullCount: 0,
frustumCullCount: 0
};
constructor() {
// 处理具有NodeComponent的实体
super(Matcher.empty().all(NodeComponent));
}
/**
* 处理所有实体
*/
protected process(entities: Entity[]): void {
this.performanceMonitor.frameStartTime = performance.now();
this.renderStats.totalNodes = entities.length;
this.renderStats.visibleNodes = 0;
this.renderStats.renderCalls = 0;
for (const entity of entities) {
this.processEntity(entity);
}
// 处理节点层次结构
this.updateNodeHierarchy(entities);
// 更新性能统计
this.updatePerformanceStats();
// 清理过期的性能缓存
this.cleanupPerformanceCache(entities);
}
/**
* 处理单个实体
*/
private processEntity(entity: Entity): void {
const nodeComponent = entity.getComponent(NodeComponent);
const transform = entity.getComponent(Transform);
const renderer = entity.getComponent(Renderer);
if (!nodeComponent) return;
const renderStartTime = performance.now();
// 确保有对应的Cocos Creator节点
this.ensureNode(nodeComponent, entity);
// 同步Transform数据
if (transform && nodeComponent.node) {
this.syncTransform(nodeComponent, transform);
}
// 同步渲染数据
if (renderer && nodeComponent.node) {
this.syncRenderer(nodeComponent, renderer);
}
// 更新节点配置
this.updateNodeConfig(nodeComponent);
// 执行视锥体剔除
const isVisible = this.performCulling(nodeComponent);
if (isVisible) {
this.renderStats.visibleNodes++;
this.performRender(nodeComponent);
}
// 更新性能统计
const renderTime = performance.now() - renderStartTime;
nodeComponent.updatePerformance(renderTime);
this.renderStats.renderCalls++;
this.renderStats.totalRenderTime += renderTime;
}
/**
* 确保节点存在
*/
private ensureNode(nodeComponent: NodeComponent, entity: Entity): void {
if (!nodeComponent.node) {
// 从对象池中获取节点或创建新节点
nodeComponent.node = this.getNodeFromPool() || new Node(nodeComponent.nodeConfig.name);
// 初始化节点
this.initializeNode(nodeComponent.node, nodeComponent, entity);
}
}
/**
* 从对象池获取节点
*/
private getNodeFromPool(): Node | null {
return this.nodePool.pop() || null;
}
/**
* 初始化节点
*/
private initializeNode(node: Node, nodeComponent: NodeComponent, entity: Entity): void {
const config = nodeComponent.nodeConfig;
// 设置基本属性
node.name = config.name;
node.layer = config.layer;
node.active = config.renderData.visible;
// 设置变换
node.setPosition(config.transformData.position);
node.setRotationFromEuler(config.transformData.rotation);
node.setScale(config.transformData.scale);
// 设置渲染属性
const opacity = Math.floor(config.renderData.opacity * 255);
// 这里可以设置更多Cocos Creator特定的属性
// 添加用户数据
config.userData.entityId = entity.id;
config.userData.componentId = nodeComponent.id;
}
/**
* 同步Transform数据
*/
private syncTransform(nodeComponent: NodeComponent, transform: Transform): void {
const node = nodeComponent.node!;
const config = nodeComponent.nodeConfig;
// 更新配置中的变换数据
config.transformData.position.set(transform.position);
config.transformData.rotation.set(transform.rotation);
config.transformData.scale.set(transform.scale);
// 同步到Cocos Creator节点
node.setPosition(transform.position);
node.setRotationFromEuler(transform.rotation);
node.setScale(transform.scale);
// 更新缓存数据
nodeComponent.complexData.cache.textureCache.set('lastPosition', transform.position.clone());
}
/**
* 同步渲染数据
*/
private syncRenderer(nodeComponent: NodeComponent, renderer: Renderer): void {
const node = nodeComponent.node!;
const config = nodeComponent.nodeConfig;
// 更新配置中的渲染数据
config.renderData.color.set(renderer.color);
config.renderData.opacity = renderer.alpha;
config.renderData.visible = renderer.visible && renderer.alpha > 0;
// 同步到Cocos Creator节点
node.active = config.renderData.visible;
// 更新材质缓存
nodeComponent.complexData.cache.materialCache.set('currentColor', renderer.color.clone());
nodeComponent.complexData.cache.materialCache.set('alpha', renderer.alpha);
}
/**
* 更新节点配置
*/
private updateNodeConfig(nodeComponent: NodeComponent): void {
const config = nodeComponent.nodeConfig;
const currentTime = Date.now();
// 更新统计信息
nodeComponent.complexData.statistics.frameCount++;
nodeComponent.complexData.statistics.lastUpdateTime = currentTime;
// 更新用户数据
config.userData.lastFrameUpdate = currentTime;
config.userData.frameCount = nodeComponent.complexData.statistics.frameCount;
// 动态调整配置
if (Math.random() < 0.01) { // 1% 概率调整
config.renderData.opacity *= (0.95 + Math.random() * 0.1); // 轻微透明度变化
config.renderData.opacity = Math.max(0.1, Math.min(1.0, config.renderData.opacity));
}
}
/**
* 执行视锥体剔除
*/
private performCulling(nodeComponent: NodeComponent): boolean {
if (!nodeComponent.node) {
return false;
}
const config = nodeComponent.nodeConfig;
// 简单的可见性检查
if (!config.renderData.visible || config.renderData.opacity <= 0) {
this.performanceMonitor.cullCount++;
return false;
}
// 距离剔除
const position = config.transformData.position;
const distance = position.length();
if (distance > 1000) { // 超过1000单位距离的对象被剔除
this.performanceMonitor.frustumCullCount++;
return false;
}
// 层级剔除
if (config.layer < 0) {
this.performanceMonitor.cullCount++;
return false;
}
return true;
}
/**
* 执行渲染
*/
private performRender(nodeComponent: NodeComponent): void {
if (!nodeComponent.node) return;
const renderStartTime = performance.now();
// 模拟复杂的渲染过程
this.simulateRenderingWork(nodeComponent);
// 更新子节点
this.updateChildNodes(nodeComponent);
// 更新着色器缓存
this.updateShaderCache(nodeComponent);
const renderTime = performance.now() - renderStartTime;
// 更新性能统计
const perf = nodeComponent.complexData.statistics.performance;
perf.renderHistory.push(renderTime);
if (perf.renderHistory.length > 100) {
perf.renderHistory.shift();
}
perf.avgRenderTime = perf.renderHistory.reduce((a, b) => a + b, 0) / perf.renderHistory.length;
perf.maxRenderTime = Math.max(perf.maxRenderTime, renderTime);
}
/**
* 模拟渲染工作
*/
private simulateRenderingWork(nodeComponent: NodeComponent): void {
const complexity = nodeComponent.complexData.cache.materialCache.size +
nodeComponent.complexData.cache.textureCache.size;
// 模拟基于复杂度的计算工作
let iterations = Math.min(complexity * 10, 1000);
let result = 0;
for (let i = 0; i < iterations; i++) {
result += Math.sin(i * 0.001) * Math.cos(i * 0.002);
}
// 存储计算结果到缓存
nodeComponent.complexData.cache.shaderCache.set('computeResult', result);
}
/**
* 更新子节点
*/
private updateChildNodes(nodeComponent: NodeComponent): void {
if (nodeComponent.children.length === 0) return;
const parentNode = nodeComponent.node!;
// 同步子节点
for (let i = 0; i < nodeComponent.children.length; i++) {
const childNode = nodeComponent.children[i];
if (childNode && childNode.parent !== parentNode) {
parentNode.addChild(childNode);
}
}
// 更新层次结构数据
nodeComponent.complexData.hierarchy.siblingIndex = parentNode.getSiblingIndex();
// 更新子组件的层次深度(需要通过实体管理器查找)
// 这里省略了复杂的查找逻辑,避免循环引用
if (nodeComponent.nodeConfig.childIds.length > 0) {
// 实际项目中应该通过实体管理器查找子实体并更新深度
// 为了示例简化,我们只更新自己的深度
nodeComponent.complexData.hierarchy.depth = Math.max(0, nodeComponent.complexData.hierarchy.depth);
}
}
/**
* 更新着色器缓存
*/
private updateShaderCache(nodeComponent: NodeComponent): void {
const shaderCache = nodeComponent.complexData.cache.shaderCache;
// 模拟着色器参数更新
const currentTime = Date.now();
shaderCache.set('time', currentTime);
shaderCache.set('frameCount', nodeComponent.complexData.statistics.frameCount);
// 清理过期的着色器缓存
if (shaderCache.size > 50) {
const keys = Array.from(shaderCache.keys());
const oldestKey = keys[0];
shaderCache.delete(oldestKey);
}
}
/**
* 更新节点层次结构
*/
private updateNodeHierarchy(entities: Entity[]): void {
// 构建层次结构映射
const nodeMap = new Map<number, NodeComponent>();
entities.forEach(entity => {
const nodeComponent = entity.getComponent(NodeComponent);
if (nodeComponent) {
nodeMap.set(entity.id, nodeComponent);
}
});
// 更新层次关系使用ID避免循环引用
nodeMap.forEach((nodeComponent, entityId) => {
// 更新根节点ID
if (!nodeComponent.complexData.hierarchy.parentId) {
nodeComponent.complexData.hierarchy.rootId = entityId;
} else {
// 查找根节点ID简化版本避免深度遍历
let currentParentId = nodeComponent.complexData.hierarchy.parentId;
let depth = 0;
// 限制深度以避免无限循环
while (currentParentId && depth < 10) {
const parentNode = nodeMap.get(currentParentId);
if (parentNode && parentNode.complexData.hierarchy.parentId) {
currentParentId = parentNode.complexData.hierarchy.parentId;
depth++;
} else {
break;
}
}
nodeComponent.complexData.hierarchy.rootId = currentParentId || entityId;
}
});
}
/**
* 更新性能统计
*/
private updatePerformanceStats(): void {
const frameTime = performance.now() - this.performanceMonitor.frameStartTime;
this.performanceMonitor.renderTimeHistory.push(frameTime);
if (this.performanceMonitor.renderTimeHistory.length > 60) {
this.performanceMonitor.renderTimeHistory.shift();
}
this.renderStats.frameCount++;
if (this.renderStats.renderCalls > 0) {
this.renderStats.averageRenderTime = this.renderStats.totalRenderTime / this.renderStats.renderCalls;
}
}
/**
* 清理性能缓存
*/
private cleanupPerformanceCache(entities: Entity[]): void {
entities.forEach(entity => {
const nodeComponent = entity.getComponent(NodeComponent);
if (nodeComponent) {
const caches = nodeComponent.complexData.cache;
// 清理纹理缓存
if (caches.textureCache.size > 100) {
const keys = Array.from(caches.textureCache.keys());
const toDelete = keys.slice(0, 20); // 删除最旧的20个
toDelete.forEach(key => caches.textureCache.delete(key));
}
// 清理材质缓存
if (caches.materialCache.size > 50) {
const keys = Array.from(caches.materialCache.keys());
const toDelete = keys.slice(0, 10); // 删除最旧的10个
toDelete.forEach(key => caches.materialCache.delete(key));
}
}
});
}
/**
* 回收节点到对象池
*/
public recycleNode(node: Node): void {
if (this.nodePool.length < 100) { // 限制对象池大小
node.removeFromParent();
node.destroyAllChildren();
this.nodePool.push(node);
} else {
node.destroy();
}
}
/**
* 系统初始化时调用
*/
public initialize(): void {
super.initialize();
console.log('🎨 节点渲染系统已启动');
// 预热对象池
for (let i = 0; i < 10; i++) {
this.nodePool.push(new Node(`PooledNode_${i}`));
}
}
/**
* 当实体被移除时
*/
protected onRemoved(entity: Entity): void {
const nodeComponent = entity.getComponent(NodeComponent);
if (nodeComponent && nodeComponent.node) {
this.recycleNode(nodeComponent.node);
nodeComponent.node = null;
}
}
/**
* 获取系统统计信息
*/
public getSystemStats(): any {
return {
...this.renderStats,
cullCount: this.performanceMonitor.cullCount,
frustumCullCount: this.performanceMonitor.frustumCullCount,
nodePoolSize: this.nodePool.length,
averageFrameTime: this.performanceMonitor.renderTimeHistory.length > 0
? this.performanceMonitor.renderTimeHistory.reduce((a, b) => a + b, 0) / this.performanceMonitor.renderTimeHistory.length
: 0,
systemName: 'NodeRenderSystem'
};
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "b4593488-685b-4e52-800b-b2a2990305d6",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -1,4 +1,7 @@
// 导出所有系统
export { MovementSystem } from './MovementSystem';
export { HealthSystem } from './HealthSystem';
export { RandomMovementSystem } from './RandomMovementSystem';
export { RandomMovementSystem } from './RandomMovementSystem';
export { AISystem } from './AISystem';
export { NetworkSystem } from './NetworkSystem';
export { NodeRenderSystem } from './NodeRenderSystem';

View File

@@ -7,7 +7,7 @@
"name": "cocos-ecs",
"dependencies": {
"@esengine/ai": "^2.0.15",
"@esengine/ecs-framework": "^2.1.22"
"@esengine/ecs-framework": "^2.1.23"
}
},
"node_modules/@esengine/ai": {
@@ -22,9 +22,10 @@
}
},
"node_modules/@esengine/ecs-framework": {
"version": "2.1.22",
"resolved": "https://registry.npmjs.org/@esengine/ecs-framework/-/ecs-framework-2.1.22.tgz",
"integrity": "sha512-U5zQJJC7eQeiIUMV1Y784rOJoVK9x8ZLDI65+8Bbt3PcBWzn+qspLe4FBlJU4XBZcMbmEo5vJltvRNkN7iVPZA==",
"version": "2.1.23",
"resolved": "https://registry.npmjs.org/@esengine/ecs-framework/-/ecs-framework-2.1.23.tgz",
"integrity": "sha512-Em4w+AQ2c/eXN6FqTwySwu869yPjG9kHZp74vEDVBLb7uQOw+g8aMrSALS4tYHTj0PxNofcNplS38xjGsFTekA==",
"license": "MIT",
"engines": {
"node": ">=16.0.0"
}

View File

@@ -5,7 +5,7 @@
"version": "3.8.6"
},
"dependencies": {
"@esengine/ecs-framework": "^2.1.22",
"@esengine/ai": "^2.0.15"
"@esengine/ai": "^2.0.15",
"@esengine/ecs-framework": "^2.1.23"
}
}
}

View File

@@ -136,6 +136,22 @@ export class DebugManager {
}
break;
case 'expand_lazy_object':
this.handleExpandLazyObjectRequest(message);
break;
case 'get_component_properties':
this.handleGetComponentPropertiesRequest(message);
break;
case 'get_raw_entity_list':
this.handleGetRawEntityListRequest(message);
break;
case 'get_entity_details':
this.handleGetEntityDetailsRequest(message);
break;
case 'ping':
this.webSocketManager.send({
type: 'pong',
@@ -149,9 +165,139 @@ export class DebugManager {
}
} catch (error) {
// console.error('[ECS Debug] 处理消息失败:', error);
if (message.requestId) {
this.webSocketManager.send({
type: 'error_response',
requestId: message.requestId,
error: error instanceof Error ? error.message : String(error)
});
}
}
}
/**
* 处理展开懒加载对象请求
*/
private handleExpandLazyObjectRequest(message: any): void {
try {
const { entityId, componentIndex, propertyPath, requestId } = message;
if (entityId === undefined || componentIndex === undefined || !propertyPath) {
this.webSocketManager.send({
type: 'expand_lazy_object_response',
requestId,
error: '缺少必要参数'
});
return;
}
const expandedData = this.entityCollector.expandLazyObject(entityId, componentIndex, propertyPath);
this.webSocketManager.send({
type: 'expand_lazy_object_response',
requestId,
data: expandedData
});
} catch (error) {
this.webSocketManager.send({
type: 'expand_lazy_object_response',
requestId: message.requestId,
error: error instanceof Error ? error.message : String(error)
});
}
}
/**
* 处理获取组件属性请求
*/
private handleGetComponentPropertiesRequest(message: any): void {
try {
const { entityId, componentIndex, requestId } = message;
if (entityId === undefined || componentIndex === undefined) {
this.webSocketManager.send({
type: 'get_component_properties_response',
requestId,
error: '缺少必要参数'
});
return;
}
const properties = this.entityCollector.getComponentProperties(entityId, componentIndex);
this.webSocketManager.send({
type: 'get_component_properties_response',
requestId,
data: properties
});
} catch (error) {
this.webSocketManager.send({
type: 'get_component_properties_response',
requestId: message.requestId,
error: error instanceof Error ? error.message : String(error)
});
}
}
/**
* 处理获取原始实体列表请求
*/
private handleGetRawEntityListRequest(message: any): void {
try {
const { requestId } = message;
const rawEntityList = this.entityCollector.getRawEntityList();
this.webSocketManager.send({
type: 'get_raw_entity_list_response',
requestId,
data: rawEntityList
});
} catch (error) {
this.webSocketManager.send({
type: 'get_raw_entity_list_response',
requestId: message.requestId,
error: error instanceof Error ? error.message : String(error)
});
}
}
/**
* 处理获取实体详情请求
*/
private handleGetEntityDetailsRequest(message: any): void {
try {
const { entityId, requestId } = message;
if (entityId === undefined) {
this.webSocketManager.send({
type: 'get_entity_details_response',
requestId,
error: '缺少实体ID参数'
});
return;
}
const entityDetails = this.entityCollector.getEntityDetails(entityId);
this.webSocketManager.send({
type: 'get_entity_details_response',
requestId,
data: entityDetails
});
} catch (error) {
this.webSocketManager.send({
type: 'get_entity_details_response',
requestId: message.requestId,
error: error instanceof Error ? error.message : String(error)
});
}
}
/**
* 处理内存快照请求
*/
@@ -174,60 +320,46 @@ export class DebugManager {
* 捕获内存快照
*/
private captureMemorySnapshot(): any {
const scene = Core.scene;
if (!scene) {
throw new Error('没有活跃的场景');
}
const entityList = (scene as any).entities;
if (!entityList?.buffer) {
throw new Error('无法访问实体列表');
}
const timestamp = Date.now();
// 1. 收集基础内存信息
// 使用专门的内存计算方法收集实体数据
const entityData = this.entityCollector.collectEntityDataWithMemory();
// 收集其他内存统计
const baseMemoryInfo = this.collectBaseMemoryInfo();
// 2. 收集实体内存统计
const entityMemoryStats = this.collectEntityMemoryStats(entityList);
// 3. 收集组件内存统计
const componentMemoryStats = this.collectComponentMemoryStats(entityList);
// 4. 收集系统内存统计
const componentMemoryStats = this.collectComponentMemoryStats((Core.scene as any)?.entities);
const systemMemoryStats = this.collectSystemMemoryStats();
// 5. 收集对象池内存统计
const poolMemoryStats = this.collectPoolMemoryStats();
// 6. 收集性能监控器统计
const performanceStats = this.collectPerformanceStats();
// 计算总内存使用量
const totalEntityMemory = entityData.entitiesPerArchetype.reduce((sum, arch) => sum + arch.memory, 0);
return {
timestamp,
version: '2.0',
summary: {
totalEntities: entityList.buffer.length,
totalEntities: entityData.totalEntities,
totalMemoryUsage: baseMemoryInfo.usedMemory,
totalMemoryLimit: baseMemoryInfo.totalMemory,
memoryUtilization: (baseMemoryInfo.usedMemory / baseMemoryInfo.totalMemory * 100),
gcCollections: baseMemoryInfo.gcCollections,
entityMemory: entityMemoryStats.totalMemory,
entityMemory: totalEntityMemory,
componentMemory: componentMemoryStats.totalMemory,
systemMemory: systemMemoryStats.totalMemory,
poolMemory: poolMemoryStats.totalMemory
},
baseMemory: baseMemoryInfo,
entities: entityMemoryStats,
entities: {
totalMemory: totalEntityMemory,
entityCount: entityData.totalEntities,
archetypes: entityData.entitiesPerArchetype,
largestEntities: entityData.topEntitiesByComponents
},
components: componentMemoryStats,
systems: systemMemoryStats,
pools: poolMemoryStats,
performance: performanceStats,
// 保持向后兼容
totalEntities: entityList.buffer.length,
totalMemory: entityMemoryStats.totalMemory,
detailedArchetypes: entityMemoryStats.archetypes
performance: performanceStats
};
}
@@ -275,87 +407,7 @@ export class DebugManager {
return memoryInfo;
}
/**
* 收集实体内存统计
*/
private collectEntityMemoryStats(entityList: any): any {
const archetypeStats = new Map<string, { count: number; memory: number; entities: any[] }>();
const entitySizeDistribution = new Map<string, number>(); // 按大小范围分布
let totalMemory = 0;
let maxEntityMemory = 0;
let minEntityMemory = Number.MAX_VALUE;
const largestEntities: any[] = [];
for (const entity of entityList.buffer) {
if (!entity || entity.destroyed) continue;
// 生成组件签名
const componentTypes = entity.components ?
entity.components.map((c: any) => c.constructor.name).sort() : [];
const signature = componentTypes.length > 0 ? componentTypes.join(',') : 'Empty';
// 计算实体内存使用
const entityMemory = this.entityCollector.estimateEntityMemoryUsage(entity);
totalMemory += entityMemory;
maxEntityMemory = Math.max(maxEntityMemory, entityMemory);
minEntityMemory = Math.min(minEntityMemory, entityMemory);
// 收集大实体信息
largestEntities.push({
id: entity.id,
name: entity.name || `Entity_${entity.id}`,
memory: entityMemory,
componentCount: componentTypes.length,
componentTypes: componentTypes
});
// 内存大小分布统计
const sizeCategory = this.getMemorySizeCategory(entityMemory);
entitySizeDistribution.set(sizeCategory, (entitySizeDistribution.get(sizeCategory) || 0) + 1);
// 更新原型统计
if (!archetypeStats.has(signature)) {
archetypeStats.set(signature, { count: 0, memory: 0, entities: [] });
}
const stats = archetypeStats.get(signature)!;
stats.count++;
stats.memory += entityMemory;
stats.entities.push({
id: entity.id,
name: entity.name || `Entity_${entity.id}`,
memory: entityMemory,
componentCount: componentTypes.length
});
}
// 排序并限制返回的实体数量
largestEntities.sort((a, b) => b.memory - a.memory);
// 转换原型统计
const archetypes = Array.from(archetypeStats.entries()).map(([signature, stats]) => ({
signature,
count: stats.count,
memory: stats.memory,
averageMemory: stats.memory / stats.count,
percentage: totalMemory > 0 ? (stats.memory / totalMemory * 100) : 0,
entities: stats.entities.sort((a, b) => b.memory - a.memory).slice(0, 5) // 只返回前5个最大的
})).sort((a, b) => b.memory - a.memory);
return {
totalMemory,
entityCount: entityList.buffer.length,
averageEntityMemory: totalMemory / entityList.buffer.length,
maxEntityMemory,
minEntityMemory: minEntityMemory === Number.MAX_VALUE ? 0 : minEntityMemory,
archetypes,
largestEntities: largestEntities.slice(0, 10),
sizeDistribution: Array.from(entitySizeDistribution.entries()).map(([category, count]) => ({
category,
count,
percentage: (count / entityList.buffer.length * 100)
}))
};
}
/**
* 收集组件内存统计

File diff suppressed because it is too large Load Diff