feat(physics): 集成 Rapier2D 物理引擎并修复预览重置问题 (#244)

* feat(physics): 集成 Rapier2D 物理引擎并修复预览重置问题

* fix: 修复 CI 流程并清理代码
This commit is contained in:
YHH
2025-11-28 10:32:28 +08:00
committed by GitHub
parent cabb625a17
commit 673f5e5855
56 changed files with 4934 additions and 218 deletions

View File

@@ -34,6 +34,14 @@ export class ComponentRegistry {
return existingIndex;
}
// 检查是否有同名但不同类的组件已注册
if (this.componentNameToType.has(typeName)) {
const existingType = this.componentNameToType.get(typeName);
if (existingType !== componentType) {
console.warn(`[ComponentRegistry] Component name conflict: "${typeName}" already registered with different class. Existing: ${existingType?.name}, New: ${componentType.name}`);
}
}
const bitIndex = this.nextBitIndex++;
this.componentTypes.set(componentType, bitIndex);
this.bitIndexToType.set(bitIndex, componentType);

View File

@@ -80,17 +80,26 @@ export function Serializable(options: SerializableOptions) {
throw new Error('Serializable装饰器必须提供有效的版本号');
}
// 初始化或获取现有元数据
let metadata: SerializationMetadata = (target as any)[SERIALIZABLE_METADATA];
if (!metadata) {
// 检查是否有自己的元数据(不是从父类继承的)
const hasOwnMetadata = Object.prototype.hasOwnProperty.call(target, SERIALIZABLE_METADATA);
let metadata: SerializationMetadata;
if (hasOwnMetadata) {
// 已有自己的元数据,更新 options
metadata = (target as any)[SERIALIZABLE_METADATA];
metadata.options = options;
} else {
// 没有自己的元数据,检查是否有继承的元数据
const inheritedMetadata: SerializationMetadata | undefined = (target as any)[SERIALIZABLE_METADATA];
// 创建新的元数据对象(从继承的元数据复制字段,但使用新的 options
metadata = {
options,
fields: new Map(),
ignoredFields: new Set()
fields: inheritedMetadata ? new Map(inheritedMetadata.fields) : new Map(),
ignoredFields: inheritedMetadata ? new Set(inheritedMetadata.ignoredFields) : new Set()
};
(target as any)[SERIALIZABLE_METADATA] = metadata;
} else {
metadata.options = options;
}
return target;
@@ -117,13 +126,22 @@ export function Serialize(options?: FieldSerializeOptions) {
return function (target: any, propertyKey: string | symbol) {
const constructor = target.constructor;
// 获取或创建元数据
let metadata: SerializationMetadata = constructor[SERIALIZABLE_METADATA];
if (!metadata) {
// 检查是否有自己的元数据(不是从父类继承的)
const hasOwnMetadata = Object.prototype.hasOwnProperty.call(constructor, SERIALIZABLE_METADATA);
let metadata: SerializationMetadata;
if (hasOwnMetadata) {
// 已有自己的元数据
metadata = constructor[SERIALIZABLE_METADATA];
} else {
// 没有自己的元数据,检查是否有继承的元数据
const inheritedMetadata: SerializationMetadata | undefined = constructor[SERIALIZABLE_METADATA];
// 创建新的元数据对象(从继承的元数据复制)
metadata = {
options: { version: 1 }, // 默认版本
fields: new Map(),
ignoredFields: new Set()
options: inheritedMetadata ? { ...inheritedMetadata.options } : { version: 1 },
fields: inheritedMetadata ? new Map(inheritedMetadata.fields) : new Map(),
ignoredFields: inheritedMetadata ? new Set(inheritedMetadata.ignoredFields) : new Set()
};
constructor[SERIALIZABLE_METADATA] = metadata;
}
@@ -208,13 +226,22 @@ export function IgnoreSerialization() {
return function (target: any, propertyKey: string | symbol) {
const constructor = target.constructor;
// 获取或创建元数据
let metadata: SerializationMetadata = constructor[SERIALIZABLE_METADATA];
if (!metadata) {
// 检查是否有自己的元数据(不是从父类继承的)
const hasOwnMetadata = Object.prototype.hasOwnProperty.call(constructor, SERIALIZABLE_METADATA);
let metadata: SerializationMetadata;
if (hasOwnMetadata) {
// 已有自己的元数据
metadata = constructor[SERIALIZABLE_METADATA];
} else {
// 没有自己的元数据,检查是否有继承的元数据
const inheritedMetadata: SerializationMetadata | undefined = constructor[SERIALIZABLE_METADATA];
// 创建新的元数据对象(从继承的元数据复制)
metadata = {
options: { version: 1 },
fields: new Map(),
ignoredFields: new Set()
options: inheritedMetadata ? { ...inheritedMetadata.options } : { version: 1 },
fields: inheritedMetadata ? new Map(inheritedMetadata.fields) : new Map(),
ignoredFields: inheritedMetadata ? new Set(inheritedMetadata.ignoredFields) : new Set()
};
constructor[SERIALIZABLE_METADATA] = metadata;
}

View File

@@ -245,6 +245,17 @@ export abstract class EntitySystem implements ISystemBase, IService {
this._entityCache.invalidate();
}
/**
* 完全重置实体跟踪状态
* 清除所有缓存和跟踪的实体,强制下次 update 时重新扫描所有实体并触发 onAdded
* 用于场景重载/预览重置等场景
*/
public resetEntityTracking(): void {
this._entityCache.clearAll();
this._entityIdMap = null;
this._entityIdMapVersion = -1;
}
/**
* 重置系统状态
*

View File

@@ -180,25 +180,6 @@ describe('ComponentRegistry Extended - 64+ 组件支持', () => {
});
});
describe('性能测试', () => {
it('大量组件注册应该高效', () => {
const startTime = performance.now();
// 注册 200 个组件
for (let i = 0; i < 200; i++) {
const ComponentClass = createTestComponent(i);
ComponentRegistry.register(ComponentClass);
}
const endTime = performance.now();
const duration = endTime - startTime;
// 应该在 100ms 内完成
expect(duration).toBeLessThan(100);
});
});
describe('边界情况', () => {
it('应该正确处理第 64 个组件(边界)', () => {
const scene = new Scene();