Files
Cocos3.8.5/assets/script/common/LoadTools.ts
ZhouXiao 487c68994d feat: add builder configuration file
feat: add cocos-service configuration file
feat: add device configuration file
feat: add engine configuration file
feat: add information configuration file
feat: add program configuration file
feat: add project configuration file
feat: add TypeScript configuration file
2025-12-22 11:42:51 +08:00

281 lines
10 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 { director, Node, instantiate, Prefab, Vec3, v3, SpriteFrame, Sprite, AssetManager, resources, assetManager, AudioClip, Material, Texture2D, Label } from "cc";
import { ResModel } from "../model/ResModel";
import { weiSan } from "./weiSanTools";
import { EventManager, EventData } from "../manager/EventManager";
import { PoolManager } from "../manager/PoolManager";
/** 加载资源相关工具类 */
export class LoadTools {
/** 单例模式 */
private static _instance: LoadTools = new LoadTools();
private constructor() { }
public static get _ins() {
return this._instance;
}
/**
* 加载游戏场景
* @param sceneName 加载场景的名字
* @param callFunc 加载回调
*/
loadScene(sceneName: string, callFunc: any, isClear = true) {
if (isClear) {
ResModel._ins.clearResDic();
}
director.preloadScene(sceneName, () => {
director.loadScene(sceneName, callFunc);
});
};
/**
* 加载resource 下的预制体 资源
* @param url resource 下的资源路径
* @param callBack 加载完成回调
*/
loadResPrefab(url: string, callBack?: any, parent?: Node, Pos?: Vec3) {
this.loadResAny(url, Prefab, (prefab: Prefab) => {
let clone = instantiate(prefab);
if (parent) { parent.addChild(clone) };
if (Pos) { clone.position = v3(Pos.x, Pos.y, 0) };
if (callBack != null) {
callBack(clone);
}
})
}
/**
* 加载resource 下的图片资源并渲染到节点上
* @param url resource 下的资源路径
* @param callBack 加载完成回调
*/
loadResSpriteFrame(url: string, sprite: Node, parent?: Node, Pos?: Vec3, callBack?: any) {
resources.load(url + "/spriteFrame", SpriteFrame, function (error: any, SpriteFrame: SpriteFrame) {
if (error) {
weiSan.error(error);
} else {
sprite.getComponent(Sprite).spriteFrame = SpriteFrame;
if (parent) { parent.addChild(sprite) };
if (Pos) { sprite.position = v3(Pos.x, Pos.y, 0) };
if (callBack != null) {
callBack(sprite);
}
}
});
};
/**
* 加载resource 下的游戏资源
* @param url resource 下的资源路径
* @param resType 加载资源的类型
* @param callBack 加载完成回调
*/
loadResAny(url: string, resType: any, callBack?: any) {
resources.load(url, resType, function (error: any, res: any) {
if (error) {
weiSan.error(error);
} else {
if (callBack != null) {
callBack(res);
}
if (resType == Prefab) {
ResModel._ins.PrefabDic.set(url, res);
} else if (resType == SpriteFrame) {
if (!ResModel._ins.SpriteFrameDic.has(url)) {
ResModel._ins.SpriteFrameDic.set(url, res);
}
} else if (resType == AudioClip) {
if (!ResModel._ins.AudioClipDic.has(url)) {
ResModel._ins.AudioClipDic.set(url, res);
}
} else if (resType == Material) {
if (!ResModel._ins.MaterialDic.has(url)) {
ResModel._ins.MaterialDic.set(url, res);
}
} else if (resType == Texture2D) {
if (!ResModel._ins.TextureDic.has(url)) {
ResModel._ins.TextureDic.set(url, res);
}
} else if (resType === Prefab) {
if (!ResModel._ins.PrefabDic.has(url)) {
ResModel._ins.PrefabDic.set(url, res);
}
}
}
});
}
/** 加载bundle 场景 */
loadBundleScene(bundleName: string, sceneName: string, onFinishBack?: () => void, isInScene: boolean = true) {
assetManager.loadBundle(
bundleName,
(err: any, bundle: AssetManager.Bundle) => {
if (err) {
console.log(err);
}
else {
if (!isInScene) { return; }
bundle.loadScene(sceneName, (err, scene) => {
if (onFinishBack) {
onFinishBack();
}
director.runScene(scene);
});
}
}
);
}
/**
* 分帧加载预制体节点
* @param prefabName 要加载的预制体名称
* @param perFrameNum 每帧加载的数量
* @param totalNum 总共需要加载的数量
* @param usePool 是否使用对象池默认为true
* @param callBack 对每个创建的节点进行操作的回调函数
* @returns Promise<Node[]> 返回所有创建的节点数组
*/
loadPrefabByFrame(prefabName: string, perFrameNum: number, totalNum: number, usePool: boolean = true, callBack?: (node: Node, index: number) => void): Promise<Node[]> {
return new Promise((resolve, reject) => {
// 参数验证
if (!prefabName || prefabName.trim() === '') {
const error = 'prefabName cannot be empty';
weiSan.error(error);
reject(new Error(error));
return;
}
if (perFrameNum <= 0) {
const error = 'perFrameNum must be greater than 0';
weiSan.error(error);
reject(new Error(error));
return;
}
if (totalNum <= 0) {
const error = 'totalNum must be greater than 0';
weiSan.error(error);
reject(new Error(error));
return;
}
// 触发加载开始事件
EventManager.dispatchEvent(EventData.PREFAB_LOAD_START, {
prefabName: prefabName,
totalNum: totalNum,
usePool: usePool
});
// 创建节点的函数
const createNodeFunction = (prefab?: Prefab): Node | null => {
if (usePool) {
// 使用对象池创建节点
return PoolManager._ins.getNode(prefabName);
} else {
// 使用传统方式创建节点
if (!prefab) {
weiSan.error(`Prefab is required when not using pool: ${prefabName}`);
return null;
}
return instantiate(prefab);
}
};
if (usePool) {
// 使用对象池时,直接开始分帧创建
this.startFrameBasedCreation(prefabName, perFrameNum, totalNum, usePool, callBack, createNodeFunction, resolve, reject);
} else {
// 不使用对象池时,先加载预制体资源
this.loadResAny(prefabName, Prefab, (prefab: Prefab) => {
if (!prefab) {
const error = `Failed to load prefab: ${prefabName}`;
weiSan.error(error);
reject(new Error(error));
return;
}
this.startFrameBasedCreation(prefabName, perFrameNum, totalNum, usePool, callBack, createNodeFunction, resolve, reject, prefab);
});
}
});
}
/**
* 开始分帧创建节点的核心逻辑
*/
private startFrameBasedCreation(
prefabName: string,
perFrameNum: number,
totalNum: number,
usePool: boolean,
callBack: ((node: Node, index: number) => void) | undefined,
createNodeFunction: (prefab?: Prefab) => Node | null,
resolve: (value: Node[]) => void,
reject: (reason?: any) => void,
prefab?: Prefab
) {
// 开始分帧创建节点
const createdNodes: Node[] = [];
let currentCount = 0;
const createNodesPerFrame = () => {
const remainingCount = totalNum - currentCount;
const currentFrameCount = Math.min(perFrameNum, remainingCount);
// 创建当前帧的节点
for (let i = 0; i < currentFrameCount; i++) {
try {
const node = createNodeFunction(prefab);
if (!node) {
const error = `Failed to create node: ${prefabName}`;
weiSan.error(error);
reject(new Error(error));
return;
}
createdNodes.push(node);
// 执行回调函数
if (callBack) {
try {
callBack(node, currentCount);
} catch (callbackError) {
weiSan.warn(`Callback error for node ${currentCount}: ${callbackError}`);
}
}
currentCount++;
} catch (error) {
weiSan.error(`Error creating node instance: ${error}`);
reject(new Error(`Error creating node instance: ${error}`));
return;
}
}
// 计算进度并触发进度事件
const progress = (currentCount / totalNum) * 100;
EventManager.dispatchEvent(EventData.PREFAB_LOAD_PROGRESS, {
prefabName: prefabName,
currentNum: currentCount,
totalNum: totalNum,
progress: progress
});
// 检查是否完成
if (currentCount >= totalNum) {
// 触发完成事件
EventManager.dispatchEvent(EventData.PREFAB_LOAD_COMPLETE, {
prefabName: prefabName,
totalNum: totalNum,
nodes: createdNodes
});
weiSan.log(`Successfully loaded ${totalNum} instances of prefab: ${prefabName}`);
resolve(createdNodes);
} else {
// 继续下一帧,使用 setTimeout 来实现分帧
setTimeout(() => {
createNodesPerFrame();
}, 0);
}
};
// 开始第一帧的创建
createNodesPerFrame();
}
}