IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> 简述小游戏资源管理方案 -> 正文阅读

[游戏开发]简述小游戏资源管理方案

引擎:CocosCreator。 语言: TS

前言:最近一个朋友和我聊天吐槽了一下cocosCreator的资源管理问题并问我有没有好的管理方案和方法,但我认为他并没有真正去尝试做一下而是人云亦云的在叙述给我听~没劲!,所以我花了2小时浏览了一下官方文档和尝试,并给了这位朋友回复;记录下来希望能够抛砖引玉获得大家更优秀的方案。

在这里插入图片描述

一、静态资源引用的管理

二、动态资源引用的管理

  • 看一下引擎为我们提供的资源释放接口:
    在这里插入图片描述

根据上面释放接口我们可以梳理成两种方式进行管理:
1、使用第一中方式,引用计数我们自定义,然后自己进行管理增加和减少,当自定义对应的资源的引用计数为0,我们手动调用资源释放接口。(不建议使用,使用比较复杂但是可正常实现资源管理)
2、我们只需要调用addRef增加引用计数,decRef减少引用计数,当引用为0的时候系统自动给我们清理。(推荐使用)

  • 如何验证资源是否被释放掉?
        //打印内存中所有的资源,可通过uuid去进行查找
        cc.assetManager.assets; 
        //内置bundle的get方式去查找对应资源类型
        cc.resources.get('path/name',cc.SpriteFrame);
  • 使用内置bundle和资源图集/图片/预制体为案例封装了一下关于资源释放,其他类型资源和其他bundle都差不多,可自行整理(建议:按场景、界面、窗口等单位去释放,而不是当一个小怪物死亡后立马就进行释放,虽然这样也可以)。
//*********************************************************//
//重点说一下这:
//因为内存中只包含一份资源,所以我的思路是:只要资源在内存中,引用计数最大是1;

//if (_asset.refCount <= 1) { _asset.addRef(); } //图片资源refCount+1
//因为图集加载进来给图集addRef()后,图集内所有的图片资源refCount都是1了,然后又对使用到的图集中图片进行addRef();目的是为了防止释放图集的时候把图片同样给释放掉。
//图片我们是进行统一释放管理的。

//释放我们提供了释放所有和释放单个,根据自己的需求进行调用。
//*********************************************************//
export default class AssetManager {
    private cachSpriteAtlas: Map<string, cc.SpriteAtlas> = new Map();
    private cachSpritFrames: Map<string, cc.SpriteFrame> = new Map();
    private cachPrefabs: Map<string, cc.Prefab> = new Map();
    //......
    //音频、数据、粒子、动画等Map资源容器
    /**
     * 内置bundle动态管理加载图集资源函数
     * @param assetPath  图集路径
     * @param assetName  图片名称
     * @param assetType  资源类型-图集类型
     * @param onComplete 完成回调
     */
    public loadByResources_SpriteAtlas(assetPath: string, assetName: string, assetType: typeof cc.Asset, onComplete: (err: Error, asset: cc.Asset) => void) {
        let _assetAtlas = <cc.SpriteAtlas>cc.resources.get(assetPath, assetType); //感觉没有什么卵用,可能读取到后会快一下。 留着吧
        if (_assetAtlas) {
            let _asset = _assetAtlas.getSpriteFrame(assetName);
            if (_asset && onComplete) { onComplete(null, _asset); }

            if (_asset.refCount <= 1) { _asset.addRef(); } //图片资源refCount+1
            if (!this.cachSpritFrames.get(assetName)) { this.cachSpritFrames.set(assetName, _asset); }
        }
        else {
            cc.resources.load(assetPath, assetType, (err: Error, assetAtlas: cc.Asset) => {
                if (err) {
                    console.warn("Error:", err);
                    return;
                }

                _assetAtlas = <cc.SpriteAtlas>assetAtlas;
                let _asset = _assetAtlas.getSpriteFrame(assetName);
                if (_asset && onComplete) { onComplete(err, _asset); }

                if (_assetAtlas.refCount == 0) { _assetAtlas.addRef(); } //图集资源refCount+1
                if (_asset.refCount <= 1) { _asset.addRef(); } //图片资源refCount+1
                if (!this.cachSpriteAtlas.get(assetPath)) { this.cachSpriteAtlas.set(assetPath, _assetAtlas); }
                if (!this.cachSpritFrames.get(assetPath + '/' + assetName)) { this.cachSpritFrames.set(assetPath + '/' + assetName, _asset); }
            })
        }
    }

    /**
     * 内置bundle动态管理加载非图集资源函数
     * @param assetPath 资源路径
     * @param assetType 资源类型
     * @param onComplete 完成回调
     */
    public loadByResources(assetPath: string, assetType: typeof cc.Asset, onComplete: (err: Error, asset: cc.Asset) => void) {
        let _asset: cc.Asset = cc.resources.get(assetPath, assetType);
        if (_asset) {
            if (onComplete) {
                onComplete(null, _asset);
            }
        }
        else {
            cc.resources.load(assetPath, assetType, (err: Error, asset: cc.Asset) => {
                if (err) {
                    console.warn("Error:", err);
                    return;
                }
                if (asset.refCount == 0) { asset.addRef(); }
                if (onComplete) { onComplete(err, asset); }

                if (assetType == cc.SpriteFrame) {
                    if (!this.cachSpritFrames.get(assetPath)) { this.cachSpritFrames.set(assetPath, <cc.SpriteFrame>asset); }
                }
                else if (assetType == cc.Prefab) {
                    if (!this.cachPrefabs.get(assetPath)) { this.cachPrefabs.set(assetPath, <cc.Prefab>asset); }
                }
            })
        }
    }

    /**
     * 释放类型资源
     * @param assetType 释放资源类型
     * @param path  释放的资源路径名称(默认=null,代表释放当前界面所有动态加载的资源类型)
     */
    public releaseByResources(assetType: typeof cc.Asset, path: string = null) {
        if (assetType == cc.SpriteAtlas) {
            this.releaseTypeAsset(this.cachSpriteAtlas, assetType, path);
        }
        else if (assetType == cc.SpriteFrame) {
            this.releaseTypeAsset(this.cachSpritFrames, assetType, path);
        }
        else if (assetType == cc.Prefab) {
            this.releaseTypeAsset(this.cachPrefabs, assetType, path);
        }
    }

    private releaseTypeAsset(cachAssets: Map<string, cc.Asset>, assetType: typeof cc.Asset, path: string) {
        if (path == null) {
            cachAssets.forEach((value, key) => {
                if (value) {
                    value.decRef();
                }
            })
            cachAssets.clear();
        }
        else {
            let _key: string = null;
            for (const [key, value] of Array.from(cachAssets.entries())) {
                if (key == path) {
                    _key = key;

                    if (value) { value.decRef();}
                    break;
                }
            }

            if(_key != null) {
                cachAssets.delete(_key);
            }
        }
    }
}


  • 因为我不想采用继承的方式去管理,所以记得在其他文件中使用的时候去初始化一下自己。比如:
其他文件.ts
 cc.Class NewClass{
    private assetManager: AssetManager = null;
    onLoad() {
        this.assetManager = new AssetManager();
    }
    start() {
        //动态加载预制体
        this.assetManager.loadByResources("item", cc.Prefab, (err, asset: cc.Prefab) => {
            let tempNode: cc.Node = cc.instantiate(asset)
            tempNode.parent = this.node;
            tempNode.position = cc.Vec3.ZERO;
        })
        //动态加载图片
        this.assetManager.loadByResources('UIImage/Bag_zhihuan', cc.SpriteFrame, (err, asset) => {
    
        });
        //动态加载图集图片
        this.assetManager.loadByResources_SpriteAtlas('UIImage/Bag', '100005', cc.SpriteFrame, (err, asset) => {
    
        });
    }

    onDestroy(){
        //释放对应类型动态加载的所有的资源
        this.assetManager.releaseByResources(cc.SpriteAtlas)
        this.assetManager.releaseByResources(cc.SpriteFrame)
        this.assetManager.releaseByResources(cc.Prefab)
        //释放单张资源(这里我根据的是路径去释放)
        this.assetManager.releaseByResources(cc.SpriteAtlas,'UIImage/Bag');//只释放这个图集
        this.assetManager.releaseByResources(cc.SpriteFrame,'UIImage/Bag_zhihuan')//只释放这张图片
        this.assetManager.releaseByResources(cc.SpriteFrame,'UIImage/Bag/100005') //只释放图集中的这张图片
        this.assetManager.releaseByResources(cc.Prefab, 'item')
    }

}
  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-10-01 17:12:29  更:2021-10-01 17:12:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/28 2:29:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码