@1240746582 写道:
Creator 版本:
目标平台:
详细报错信息,包含调用堆栈:
重现方式:
之前哪个版本是正常的 :
手机型号 :
手机浏览器 :
编辑器操作系统 :
编辑器之前是否有其它报错 :
出现概率:
额外线索:
帖子: 1
参与者: 1
@1240746582 写道:
Creator 版本:
目标平台:
详细报错信息,包含调用堆栈:
重现方式:
之前哪个版本是正常的 :
手机型号 :
手机浏览器 :
编辑器操作系统 :
编辑器之前是否有其它报错 :
出现概率:
额外线索:
帖子: 1
参与者: 1
@1325144990 写道:
比如我项目中有个2张完全一样的图片,他们的九宫格设置也一样,我能否通过自定义构建流程来实现,图片去重的功能,即打包完后相同的图片只保留一张。
(ps: 不要讨论我为什么会保留2张一样的图片...)
帖子: 1
参与者: 1
@642167809 写道:
Creator 版本:
目标平台:
详细报错信息,包含调用堆栈:
重现方式:
之前哪个版本是正常的 :
手机型号 :
手机浏览器 :
编辑器操作系统 :
编辑器之前是否有其它报错 :
出现概率:
额外线索:
帖子: 1
参与者: 1
@1129652464 写道:
TypeError
line:3,column:466580,TypeError: Attempted to assign to readonly property. Stack:https://resources/engine/cocos2d/core/platform/instantiate-jit.js:138:37
n@https://resources/engine/gulp/browserify_prelude.js:23:1
https://resources/engine/gulp/browserify_prelude.js:24:1
https://resources/engine/cocos2d/core/platform/instantiate-jit.js:37:20
n@https://resources/engine/gulp/browserify_prelude.js:23:1
https://resources/engine/gulp/browserify_prelude.js:24:1
https://resources/engine/cocos2d/core/index.js:49:9
n@https://resources/engine/gulp/browserify_prelude.js:23:1
帖子: 1
参与者: 1
@fu692150 写道:
gameSubContextThirdScriptError
Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The image argument is a canvas element with a width or height of 0.;at requestAnimationFrame callback function
Error: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The image argument is a canvas element with a width or height of 0.1.9.3的子域用2.0.10打开就这样
帖子: 1
参与者: 1
@704841872 写道:
球撞墙做弹射运动,各自绑上刚体与碰撞组件,用自带的物理效果弹射就得偏差严重,为了精确的计算弹射路径就需要用到碰撞时墙的法向量,我看到返回的碰撞信息有 contacts,里面有 normal,但无论我怎么摆墙的角度,normal永远都是Vec3 {x: -0, y: 1, z: -0},请问是这BUG吗?我又如何获得正确的碰撞法线呢?
帖子: 1
参与者: 1
@237786026 写道:
这篇文章是在Cocos Creator 通用框架设计 —— 资源管理的基础上,实现了静态场景资源的引用关系,所以阅读前请先阅读上面的那篇文章。
首先非常感谢宝爷的无私奉献,他提出的这个资源管理的方案我是非常认同的,之前就一直想要写一个奈何水平不够。
宝爷的实现只针对动态资源做了一个管理,对于
场景资源
和动态组件
有过文字上的建议。我们项目用到了,所以遇到的这些问题在解决和初步测试之后,第一时间跟大家分享,有问题及时反馈,共同进步。关于场景资源的建议:
关于动态组件的建议:
接下来就跟大家分享一下我自己的理解和处理方案。
Github工程地址:点这里
场景的加载和预加载
场景分为加载和预加载两种,在建立资源引用关系的过程中,这两种是要分开对待。
场景加载
如果你用cc.director.loadScene来加载一个场景,那么你最终会得到一个cc.Scene,你可以在loadScene的onLaunched回调函数获取scene,或者是通过cc.director.getScene()获取。获取的结果如下:
其中dependAssets字段就是该场景所依赖的所有资源(直接依赖和间接依赖都在这里)。
场景预加载
首先来看下preloadScene函数
preloadScene(sceneName: string, onProgress?: (completedCount: number, totalCount: number, item: any) => void, onLoaded?: (error: Error, asset: SceneAsset) => void): void;
可以看到,onLoaded回调函数的第二个参数返回的是cc.SceneAsset。当我们用preloadScene预加载一个场景时,可以得到这样的结果:
cc.Scene只是cc.SceneAsset的一个变量。而在预加载的时候,cc.Scene里面的dependAssets并没有数据。
那么,对于预加载的场景,我们要怎么获取到它的资源引用关系呢?
对于预加载的场景,虽然cc.Scene的dependAssets没有数据,但是cc.SceneAsset并没有被释放掉,我们可以通过cc.SceneAsset的_uuid(这里是2d8df980-044a-4caf-add3-e3464e761aaf)去获取资源Item,通过Item的dependKeys就可以获取直接依赖的资源,这样就可以建立起预加载场景资源的引用关系了。
场景资源的引用关系
建立引用关系的代码实现
/** * 建立场景的资源引用关系 * @param asset cc.SceneAsset */ public initSceneResDeps(asset?: cc.SceneAsset) { let addDependKey = (item, refKey) => { if (item && item.dependKeys && Array.isArray(item.dependKeys)) { for (let depKey of item.dependKeys) { // 记录这个资源被引用 this.getCacheInfo(depKey).refs.add(refKey); // console.log('refs', depKey, refKey); let ccloader: any = cc.loader; let depItem = ccloader._cache[depKey]; addDependKey(depItem, refKey); } } } // 预加载场景传入asset if (asset) { let uuid = asset['_uuid']; SceneUuidMap.set(asset.name, uuid); if (this._loadedSceneRecord.indexOf(uuid) != -1) { return; } this._loadedSceneRecord.push(uuid); let useKey = ResourceLoader.createUseKey(`Scene_${asset.name}`); let ccloader: any = cc.loader; let refKey = ccloader._getReferenceKey(uuid); // 通过uuid来获取item,这个item会在loadScene之后删除 let item = ccloader._cache[refKey]; if (asset.scene.autoReleaseAssets) { console.error(`当前场景${asset.name}不能设置为自动释放资源`); } console.log(`为预加载场景${asset.name}建立其所依赖的资源引用关系`); // 给所有依赖的资源添加ref addDependKey(item, uuid); // 给直接依赖的资源添加use for (let i = 0; i < item.dependKeys.length; i++) { let depItem = this._getResItem(item.dependKeys[i]); this.getCacheInfo(depItem.id).uses.add(useKey); } } else { // 这里为什么不用uuid去获取item呢,因为在cc.AssetLibrary.loadAsset方法,加载完场景之后会将该item移除,不知道为何 // 所以这里获取dependAssets,dependAssets记录着场景直接和间接引用的所有资源 let scene = cc.director.getScene(); let dependAssets: Array<string> = scene['dependAssets']; SceneUuidMap.set(scene.name, scene.uuid); if (this._loadedSceneRecord.indexOf(scene.uuid) != -1) { return; } this._loadedSceneRecord.push(scene.uuid); if (scene.autoReleaseAssets) { console.error(`当前场景${scene.name}不能设置为自动释放资源`); } console.log(`为场景${scene.name}建立其所依赖的资源引用关系`); // 直接依赖的refs添加scene.uuid,uses添加场景useKey // 非直接依赖的refs添加scene.uuid let useKey = ResourceLoader.createUseKey(`Scene_${scene.name}`); for (let i = 0; i < dependAssets.length; i++) { let item = this._getResItem(dependAssets[i]); let info = this.getCacheInfo(item.id); if (!info.refs.has(scene.uuid)) { this.getCacheInfo(item.id).refs.add(scene.uuid); this.getCacheInfo(item.id).uses.add(useKey); addDependKey(item, scene.uuid); } } } }
这里我自己封装了场景加载和预加载的工具类
SceneUtil
,并且在适当的时机调用initSceneResDeps
方法。public static preloadScene(sceneName: string, onProgress?: (completedCount: number, totalCount: number, item: any) => void, onLoaded?: (error: Error, asset: cc.SceneAsset) => void) { cc.director.preloadScene(sceneName, onProgress, (error: Error, asset: cc.SceneAsset) => { ResourceLoader.getInstance().initSceneResDeps(asset); onLoaded && onLoaded(error, asset); }) } public static switchScene(sceneName: string, onLaunched?: Function) { SceneUtil.lastSceneName = cc.director.getScene().name; cc.director.loadScene(sceneName, (err, scene: cc.Scene) => { onLaunched && onLaunched(err, scene); ResourceLoader.getInstance().initSceneResDeps(); // 必须先建立新场景的资源关系,再释放上一个场景 ResourceLoader.getInstance().releaseSceneResDeps(SceneUtil.lastSceneName); }); }
建立结果
一个场景A:
场景A + 场景B:
释放引用关系的代码实现
/** * 释放指定场景引用的资源 * @param sceneName */ public releaseSceneResDeps(sceneName: string) { console.log(`释放场景${sceneName}所依赖的资源`); let useKey = ResourceLoader.createUseKey(`Scene_${sceneName}`); let uuid = SceneUuidMap.get(sceneName); let index = this._loadedSceneRecord.indexOf(uuid); this._loadedSceneRecord.splice(index, 1); let release = (item, refKey) => { let cacheInfo = this.getCacheInfo(item.id); cacheInfo.refs.delete(refKey); let delDependKey = (item, refKey) => { if (item && item.dependKeys && Array.isArray(item.dependKeys)) { for (let depKey of item.dependKeys) { let ccloader: any = cc.loader; let depItem = ccloader._cache[depKey]; if (depItem) release(depItem, refKey); } } }; delDependKey(item, refKey); if (cacheInfo.uses.size == 0 && cacheInfo.refs.size == 0) { // console.log('release item ', item); // 如果没有uuid,就直接释放url if (item.uuid) { cc.loader.release(item.uuid); // cc.log('resource leader relase item by uuid :' + item.uuid); } else { cc.loader.release(item.id); // cc.log('resource leader relase item by id :' + item.id); } this._resMap.delete(item.id); } } this._resMap.forEach((value, key) => { // 找到场景使用到的资源,将其释放,同时会递归释放其依赖的资源 if (value.uses.has(useKey)) { let item = this._getResItem(key); value.uses.delete(useKey); release(item, uuid); } }); }
测试切换场景
这里提供了一个测试小工具
右上角输入框输入res就会打印出所有的资源引用关系,res空格+查询内容支持模糊查询。
右上角输入框输入item就会打印出cc.loader['_cache']的内容,同样也是item空格+查询内容支持模糊查询。
场景A切换到场景B
查看资源引用关系
切换场景B后查看资源引用关系
Github工程地址:点这里
帖子: 1
参与者: 1
@halx99 写道:
免费社区版下载地址:
https://github.com/simdsoft/x-studio/releases/download/10.0.5900.299/x-studio-Community_10.0.5900.299.exe
社区版和专业版区别:
专业版可前往官网下载
帖子: 1
参与者: 1
@13020000635 写道:
1.对off的使用不是很理解,想问下大家什么场景下需要off掉事件呢?什么场景需要用到destroy方法呢?
2. off 掉事件是这个写法 this.node.off(cc.Node.EventType.TOUCH_START, this.memberFunction, this)
那如果我注册事件是这种写法那off的第二个参数应该如何写呢?谢谢~~
帖子: 1
参与者: 1
@bl_zwjs 写道:
cc.loader.load({type:"uuid", uuid:"a4c5b53e-030d-4bf8-9e7d-ee2a1163428a"}, function (err, _obj) {
if(!err && _obj){
var item_node = new cc.Node();
var sf = itemnode.addComponent(cc.Sprite);
_sf.spriteFrame = _obj;
this.loadResSucc(item_node,map_width,map_height)
}
}.bind(this))
sf.spriteFrame = _obj;的时候报spriteFrame.textureLoaded is not a function.这个错是为啥
帖子: 1
参与者: 1
@1562292439 写道:
Creator 版本:
目标平台:
详细报错信息,包含调用堆栈:
重现方式:
之前哪个版本是正常的 :
手机型号 :
手机浏览器 :
编辑器操作系统 :
编辑器之前是否有其它报错 :
出现概率:
额外线索:
帖子: 1
参与者: 1
@863379787 写道:
Creator 版本:2.1.14
目标平台: 微信开发者工具
详细报错信息,包含调用堆栈:in libs/engine/downloader.js 'require' requires one and only one staticteral
重现方式:微信开发者工具上传代码进行代码保护
之前哪个版本是正常的 :2.1.12
手机型号 :
手机浏览器 :
编辑器操作系统 :
编辑器之前是否有其它报错 :
出现概率:
额外线索:
帖子: 1
参与者: 1
@536406747 写道:
在开发工具中进行测试可以看到有拖尾 但是发布后拖尾不显示。
做的一个小的例子
开发工具代码如下
场景的脚本就是调用动画让子弹 来回飞。
如下:
在bullet 上面加了拖尾。发布后没有显示,但是预览可以看到拖尾。T_T.
帖子: 1
参与者: 1