Appearance
Cocos Creator 资源动态加载
在游戏开发中,并非所有资源都需要在启动时加载完毕。将资源放在 resources 目录下,按需动态加载,可以有效缩短初始加载时间、降低内存占用。
基本规则
- 需要动态加载的资源必须放在
resources/目录下(或其子目录) - 加载完成后要及时释放不再使用的资源,防止内存泄漏
- 2.x 使用引用计数(
release);3.x 使用decRef()或releaseAsset()
2.x
加载单个资源
ts
// 加载图片
cc.loader.loadRes("images/hero", cc.SpriteFrame, (err, spriteFrame) => {
if (err) {
cc.error("加载失败:", err);
return;
}
this.heroSprite.spriteFrame = spriteFrame;
});
// 加载预制体
cc.loader.loadRes("prefabs/Enemy", cc.Prefab, (err, prefab) => {
if (err) return;
const enemy = cc.instantiate(prefab);
this.node.addChild(enemy);
});加载整个目录
ts
cc.loader.loadResDir("maps", cc.JsonAsset, (err, assets) => {
if (err) return;
assets.forEach(asset => {
cc.log("加载到地图:", asset.name, asset.json);
});
});释放资源(避免内存泄漏)
ts
// 释放单个资源
cc.loader.releaseRes("images/hero", cc.SpriteFrame);
// 释放整个目录下的资源
cc.loader.releaseResDir("maps");3.x
加载单个资源
ts
// 加载图片
resources.load("images/hero", SpriteFrame, (err, spriteFrame) => {
if (err) {
console.error("加载失败:", err);
return;
}
this.heroSprite.spriteFrame = spriteFrame;
});
// 加载预制体(async/await 写法)
async loadEnemy() {
return new Promise<Prefab>((resolve, reject) => {
resources.load("prefabs/Enemy", Prefab, (err, prefab) => {
if (err) { reject(err); return; }
resolve(prefab);
});
});
}加载整个目录
ts
resources.loadDir("maps", JsonAsset, (err, assets) => {
if (err) return;
assets.forEach(asset => {
console.log("加载到地图:", asset.name, asset.json);
});
});释放资源(引用计数)
3.x 使用引用计数管理资源生命周期:
ts
// 方式一:减少引用计数(引用为0时自动释放)
spriteFrame.decRef();
// 方式二:强制释放(不推荐,可能引发其他地方报错)
assetManager.releaseAsset(spriteFrame);注意:
decRef()只在资源引用计数降为 0 时才真正释放,通常配合addRef()手动管理:ts// 加载时增加引用 asset.addRef(); // 使用完毕后减少引用 asset.decRef();
常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 资源加载不到 | 文件不在 resources/ 目录下 | 将资源移入 resources/ 子目录 |
| 内存持续增长 | 加载后未释放 | 切换场景时调用 release/decRef |
| 释放后报错 | 资源被多处引用 | 2.x 改用引用计数;3.x 使用 addRef/decRef |