能给个demo么,我这边简单测试了下 spriteFrame 和 texture 都是1
还真是,我试了下
测试步骤是这样
加载一个texture2d对象A并调用A.addRef();
A的refCount 加一;
加载A的spriteFrame对象资源A1,并调用A1.addRef();
A的refCount 加一;
加载一个绑定“包含一个@property(cc.Texture2D)private texture: cc.Texture2D = null;,并将A拖到该属性”的脚本的prefabB并调用B.addRef();
A的refCount 加一;
加载一个拖入spriteFrameA1的prefabC并调用C.addRef()
A的refCount 不变;
等我拆个DEMO
为什么以模块为单位释放时就不需要引用计数了?
既然你都知道哪个模块要用,哪个模块不用,那就直接像旧版本那样无脑释放就好了。引用计数是用来解决模块之间有资源复用的情况的。
1.之前用分模块管理的时候,无法完美解决模块间的复杂引用关系问题
2.现在用引用计数解决这个复杂引用关系问题,但是发现引擎没有很友好的支持分模块管理
问题:一般项目的资源管理很难以单资源作为管理粒度,表面上管理起来很简单,加减操作,soeasy。但是很多时候加和减是没法配套的,如果不理解这个配套问题,举例:我在任何时候要加载任何东西,但是我只在一个地方释放,那么我在这个地方如何优雅的找到之前加载的东西呢?自己缓存起来?当然这个时候分目录管理是最合适,我直接释放一个目录,爽!但是引用计数不能真实的提现一个资源是否在当前运行环境有用,盲目释放目录,可能造成引用计数错误的情况。那就只能配套API === 加载目录=>释放目录,但是有时候我真的不想盲目的加载一个目录,而是更想按需加载…
唉 怎么办呢?不管是以场景做为粒度,还是以bundle作为粒度,都避不开上诉问题
如果真想做到无脑释放资源,我觉得必须要用到 “环境标记法”。每次释放都必须经过一次环境标记,未被标记的资源可以安全释放,但是由于环境标记法无法随时随地调用(因为环境标记一次需要遍历当前环境资源,随时调用存在效率问题)。
给开发者提供一个假释放接口,用来收集即将被释放的列表。当时机合适时 做一次环境标记,然后释放掉安全资源。
时机:1场景切换,2提供一个真实释放接口
这种环境标记法,我经过一年的线上测试,没有什么问题
我们讨论了一下,目前关联到场景中的动态资源,释放起来还是比较蛋疼的。是因为这个原因所以找不到之前加载的东西吗?如果不是跟场景有关的话,应该不会有问题?
可能你误解我说的“按模块释放”的意思了,我的意思是在一个特定的代码范围(模块)内重复使用某个资源时,为了不那么麻烦和中间的其他问题而只在代码范围开始前增加一次计数,结束前减少一次计数
有一张英雄图片,A 模块假设是包括匹配和选择英雄,加载中,游戏中,游戏结算这样的整个关卡流程(当然实际上不会这么分模块)
那可以在匹配刚开始把这张图片加载并计数,在游戏结算再减少计数,这样视情况而定就不至于每次用到都需要计数
还是很难用文字描述。简单说就是:2.4的引用计数已经比之前好的太多了,但是真实体验,没有预期的方便。嗯,应该就是这样总结的
有赞同的吗?我是一个人吗?
我觉得要开放引用计数的接口就应该弃用release相关的接口。最好的方式应该引擎内部通过引用计数来对资源进行管理,但是对于开发人员只需要操作资源加载和释放。
嗯,这些还差些最佳实践的方案
Prefab里拖了一个SpriteFrame,SpriteFrame引用了Texture,理论上Texture应该加一变成4吧
@869751569 说的 “自己缓存起来” 就是我觉得的,现在我能想到的,最适合手动引用计数的使用方式,虽然听起来很不必要,为什么要自己又缓存一遍,但现在看了这几种其他的方式之后我依然觉得是最合适的。
1.封装一个“模块资源管理类”,第一次加载进行 addRef,之后只读取缓存,当调用 destroy 时对所有缓存到的资源 decRef
2.有签到,抽奖,任务,收集,大厅,玩法等一些零散的东西,一般都会按这样的模块分给不同的人做,只需要告诉他创建模块资源管理实例,需要加载资源时用实例方法加载资源,在模块销毁时调用模块资源管理实例的 destroy 即可
这样其实开发人员就只需要做加载和释放操作,他可以不知道引用计数,只需要知道自己做的东西的生命周期即可。
对于签到,抽奖,任务弹框类的生命周期很简单的模块,打开即开始,关闭即销毁的非常适合,如果是其他的如全局公告跑马灯这种模块,还是可以用其他类似的办法去降低手动引用计数使用上的麻烦,但绝大多数的东西都是有简单的,明确的生命周期的
不会的,资源只会对其直接引用的资源增引用。不会管间接引用的资源。所以第四种情况,spriteFrame 的引用会增加,但是 texture 的不会
重新测试了下,直接拖动到编辑器的图片,引用计数是对对。但是有个疑问,在destroy一个精灵的时候,是否需要手动对精灵引用的spriteFrame进行释放?测试结果是销毁精灵后,它所使用的spf和tex2d的引用计数没变还是1, 这个按说在节点销毁时,应该可以自动把引用的资源释放掉吧?
start () {
let spf: cc.SpriteFrame = this.testSp.spriteFrame;
let tex2d: cc.Texture2D = spf.getTexture();
cc.log('spfRef: ', spf.refCount); // 1
cc.log('texRef:', tex2d.refCount); // 1
// spf.decRef(); // 这里如果打开则下面都是0,0
this.testSp.destroy();
this.scheduleOnce(t=>{
cc.log('spfRef: ', spf.refCount); //
cc.log('texRef:', tex2d.refCount); // 1
}, 0);
}

