1. 存储模块全面优化,修复跨平台兼容性问题,完美支持所有Unicode字符

2. 存储模块性能提升,添加LRU缓存、批量操作支持,优化内存使用
3. 多语言模块性能与内存管理优化,组件查询性能提升
4. 时间模块类型安全与性能优化,使用泛型替代any,对象池机制减少内存分配
5. 事件系统修复双重注册、重复注册等严重问题,实现EventData对象池减少GC压力
6. RandomManager修复4个逻辑BUG,包括边界问题和越界问题
7. 音频模块内存与性能优化,避免重复加载,优化数据结构,添加完整清理机制
8. CCView与CCViewVM合并,支持按需启用MVVM
9. Collection模块优化,AsyncQueue添加队列容量限制,Collection查询性能提升
10. ECS系统全面优化,对象池复用减少内存分配,循环性能提升
11. 优化MVVM组件性能
This commit is contained in:
dgflash
2026-01-09 21:54:05 +08:00
parent 9a156d5c62
commit f2fe9d47b6
85 changed files with 4356 additions and 1807 deletions

View File

@@ -8,81 +8,158 @@ import { Component, game } from 'cc';
import { StringUtil } from '../../utils/StringUtil';
import { Timer } from './Timer';
interface ITimer {
/** 定时器数据接口 */
interface ITimer<T = Record<string, number>> {
/** 倒计时编号 */
id: string;
/** 定时器 */
timer: Timer;
/** 数据对象 */
object: any;
/** 数据对象 - 必须包含数字类型的字段 */
object: T;
/** 修改数据对象的字段 */
field: string;
field: keyof T;
/** 事件侦听器的目标和被叫方 */
target: any;
target: object;
/** 开始时间 */
startTime: number;
/** 每秒触发事件 */
onSeconds: Function[];
onSeconds: Function[] | null;
/** 时间完成事件 */
onCompletes: Function[];
onCompletes: Function[] | null;
}
/** 时间管理 */
export class TimerManager extends Component {
/** 倒计时数据 */
private times: { [key: string]: ITimer } = {};
/** 服务器时间 */
/** 倒计时数据 - 使用 Map 提高性能 */
private times: Map<string, ITimer<Record<string, number>>> = new Map();
/** 服务器时间 - 复用对象减少 GC */
private date_s: Date = new Date();
/** 服务器初始时间 */
private date_s_start: Date = new Date();
/** 服务器时间后修正时间 */
private polymeric_s = 0;
/** 客户端时间 */
/** 客户端时间 - 复用对象减少 GC */
private date_c: Date = new Date();
/** 待删除的定时器 ID 缓存池,避免遍历时删除 */
private pendingRemove: string[] = [];
/** ITimer 对象池,减少对象创建开销 */
private timerPool: ITimer<Record<string, number>>[] = [];
/** 后台管理倒计时完成事件 */
protected update(dt: number) {
for (const key in this.times) {
const data = this.times[key];
protected update(dt: number): void {
// 清空待删除列表
this.pendingRemove.length = 0;
// 使用 for...of 遍历 Map.values(),性能优于 forEach
for (const data of this.times.values()) {
const timer = data.timer;
if (timer.update(dt)) {
if (data.object[data.field] > 0) {
data.object[data.field]--;
const value = data.object[data.field];
if (value > 0) {
data.object[data.field] = value - 1;
const newValue = data.object[data.field];
// 倒计时结束触发
if (data.object[data.field] == 0) {
if (newValue === 0) {
this.pendingRemove.push(data.id);
this.onTimerComplete(data);
}
// 触发每秒回调事件
else if (data.onSeconds) {
data.onSeconds.forEach((fn) => fn.call(data.object));
else if (data.onSeconds && data.onSeconds.length > 0) {
// 使用 for 循环替代 forEach减少函数调用开销
const callbacks = data.onSeconds;
const len = callbacks.length;
for (let i = 0; i < len; i++) {
callbacks[i].call(data.object);
}
}
}
}
}
// 延迟删除已完成的定时器,避免遍历时修改 Map
if (this.pendingRemove.length > 0) {
for (let i = 0; i < this.pendingRemove.length; i++) {
this.times.delete(this.pendingRemove[i]);
}
}
}
/** 触发倒计时完成事件 */
private onTimerComplete(data: ITimer) {
if (data.onCompletes) data.onCompletes.forEach((fn) => fn.call(data.target, data.object));
delete this.times[data.id];
private onTimerComplete(data: ITimer<Record<string, number>>): void {
if (data.onCompletes && data.onCompletes.length > 0) {
// 使用 for 循环替代 forEach减少函数调用开销
const callbacks = data.onCompletes;
const len = callbacks.length;
for (let i = 0; i < len; i++) {
callbacks[i].call(data.target, data.object);
}
}
// 清理内存
this.cleanupTimer(data);
}
/** 清理定时器相关引用,防止内存泄漏 */
private cleanupTimer(data: ITimer<Record<string, number>>): void {
if (data.timer) {
data.timer.destroy();
data.timer = null!;
}
// 清空回调数组并回收到对象池
if (data.onSeconds) {
data.onSeconds.length = 0;
data.onSeconds = null;
}
if (data.onCompletes) {
data.onCompletes.length = 0;
data.onCompletes = null;
}
// 清空引用
data.object = null!;
data.target = null!;
// 回收 ITimer 对象到对象池(限制池大小避免内存浪费)
if (this.timerPool.length < 50) {
this.timerPool.push(data);
}
}
/** 从对象池获取或创建新的 ITimer 对象 */
private acquireTimer<T extends Record<string, number>>(): ITimer<T> {
if (this.timerPool.length > 0) {
// 从对象池获取时需要类型断言,因为池中的对象会被重新赋值
return this.timerPool.pop() as unknown as ITimer<T>;
}
// 创建新对象
return {
id: '',
timer: null!,
object: null!,
field: '' as keyof T,
target: null!,
startTime: 0,
onSeconds: null,
onCompletes: null
};
}
/**
* 在指定对象上注册一个倒计时的回调管理器
* @param object 注册定时器的对象
* @param field 时间字段
* @template T 数据对象类型,必须包含数字类型的字段
* @param object 注册定时器的对象(必须包含可数字递减的字段
* @param field 时间字段名(必须是 object 中数字类型的字段)
* @param target 触发事件的对象
* @param onSecond 每秒事件
* @param onComplete 倒计时完成事件
* @param onSecond 每秒事件回调
* @param onComplete 倒计时完成事件回调
* @returns 倒计时编号
* @example
export class Test extends Component {
private timeId!: string;
private data = { countDown: 10 };
start() {
// 在指定对象上注册一个倒计时的回调管理器
this.timeId = oops.timer.register(this, "countDown", this, this.onSecond, this.onComplete);
this.timeId = oops.timer.register(this.data, "countDown", this, this.onSecond, this.onComplete);
}
private onSecond() {
@@ -94,24 +171,44 @@ export class TimerManager extends Component {
}
}
*/
register(object: any, field: string, target: object, onSecond?: Function, onComplete?: Function): string {
register<T extends Record<string, number>>(
object: T,
field: keyof T,
target: object,
onSecond?: Function,
onComplete?: Function
): string {
const timer = new Timer();
timer.step = 1;
const data: ITimer = {
id: StringUtil.guid(),
timer: timer,
object: object,
field: field,
onSeconds: [],
onCompletes: [],
target: target,
startTime: this.getTime()
};
if (onSecond) data.onSeconds.push(onSecond);
if (onComplete) data.onCompletes.push(onComplete);
// 从对象池获取 ITimer 对象
const data = this.acquireTimer<T>();
data.id = StringUtil.guid();
data.timer = timer;
data.object = object;
data.field = field;
data.target = target;
data.startTime = this.getTime();
this.times[data.id] = data;
// 只在需要时创建数组,减少内存分配
if (onSecond) {
data.onSeconds = data.onSeconds || [];
data.onSeconds.push(onSecond);
}
else {
data.onSeconds = null;
}
if (onComplete) {
data.onCompletes = data.onCompletes || [];
data.onCompletes.push(onComplete);
}
else {
data.onCompletes = null;
}
// 类型断言:将泛型类型转换为通用类型存储
this.times.set(data.id, data as unknown as ITimer<Record<string, number>>);
return data.id;
}
@@ -121,11 +218,50 @@ export class TimerManager extends Component {
* @param onSecond 每秒事件
* @param onComplete 倒计时完成事件
*/
addCallback(id: string, onSecond?: Function, onComplete?: Function) {
const data = this.times[id];
addCallback(id: string, onSecond?: Function, onComplete?: Function): void {
const data = this.times.get(id);
if (data) {
if (onSecond) data.onSeconds.push(onSecond);
if (onComplete) data.onCompletes.push(onComplete);
// 检查回调是否已存在,避免重复添加
if (onSecond) {
if (!data.onSeconds) {
data.onSeconds = [];
}
if (!data.onSeconds.includes(onSecond)) {
data.onSeconds.push(onSecond);
}
}
if (onComplete) {
if (!data.onCompletes) {
data.onCompletes = [];
}
if (!data.onCompletes.includes(onComplete)) {
data.onCompletes.push(onComplete);
}
}
}
}
/**
* 移除指定倒计时的回调事件
* @param id 倒计时编号
* @param onSecond 要移除的每秒事件
* @param onComplete 要移除的倒计时完成事件
*/
removeCallback(id: string, onSecond?: Function, onComplete?: Function): void {
const data = this.times.get(id);
if (data) {
if (onSecond && data.onSeconds) {
const index = data.onSeconds.indexOf(onSecond);
if (index > -1) {
data.onSeconds.splice(index, 1);
}
}
if (onComplete && data.onCompletes) {
const index = data.onCompletes.indexOf(onComplete);
if (index > -1) {
data.onCompletes.splice(index, 1);
}
}
}
}
@@ -146,8 +282,27 @@ export class TimerManager extends Component {
}
}
*/
unRegister(id: string) {
if (this.times[id]) delete this.times[id];
unRegister(id: string): void {
const data = this.times.get(id);
if (data) {
this.cleanupTimer(data);
this.times.delete(id);
}
}
/**
* 检查指定 id 的定时器是否存在
* @param id 倒计时编号
*/
has(id: string): boolean {
return this.times.has(id);
}
/**
* 获取当前活跃的定时器数量
*/
getTimerCount(): number {
return this.times.size;
}
/**
@@ -188,22 +343,62 @@ export class TimerManager extends Component {
/** 游戏最小化时记录时间数据 */
save(): void {
for (const key in this.times) {
const data: ITimer = this.times[key];
data.startTime = this.getTime();
const currentTime = this.getTime();
// 使用 for...of 替代 forEach提高性能
for (const data of this.times.values()) {
data.startTime = currentTime;
}
}
/** 游戏最大化时恢复时间数据 */
load(): void {
for (const key in this.times) {
const data = this.times[key];
const interval = Math.floor((this.getTime() - (data.startTime || this.getTime())) / 1000);
data.object[data.field] = data.object[data.field] - interval;
const currentTime = this.getTime();
// 清空待删除列表
this.pendingRemove.length = 0;
// 使用 for...of 替代 forEach提高性能
for (const data of this.times.values()) {
const interval = Math.floor((currentTime - (data.startTime || currentTime)) / 1000);
const currentValue = data.object[data.field];
data.object[data.field] = currentValue - interval;
if (data.object[data.field] <= 0) {
data.object[data.field] = 0;
this.pendingRemove.push(data.id);
this.onTimerComplete(data);
}
}
// 延迟删除已完成的定时器
if (this.pendingRemove.length > 0) {
for (let i = 0; i < this.pendingRemove.length; i++) {
this.times.delete(this.pendingRemove[i]);
}
}
}
}
/**
* 清理所有定时器,释放内存
* 注意:此方法会清除所有正在运行的定时器
*/
clear(): void {
// 使用 for...of 替代 forEach提高性能
for (const data of this.times.values()) {
this.cleanupTimer(data);
}
this.times.clear();
// 清空待删除列表
this.pendingRemove.length = 0;
}
/**
* 组件销毁时清理所有资源
*/
protected onDestroy(): void {
this.clear();
// 清理对象池
this.timerPool.length = 0;
}
}