启用了某个场景的资源自动释放后,如果在脚本中保存了对该场景的资源的“特殊引用”,则当场景切换后,由于资源已经被释放,这些引用可能会变成非法的,有可能引起渲染异常等问题。为了让这部分资源在场景切换时不被释放,我们可以使用 Asset.addRef 增加引用计数来锁住这些资源。
“特殊引用”:以全局变量、单例、闭包、“动态资源”等形式进行的引用。
“动态资源”:在脚本中动态创建或动态修改的资源。
与Unity类似,CocosCreator3.0 工作流 也是以组件化为核心的。
比如说Mesh组件
需要**注意的是,**一个节点上只能添加一个渲染组件(MeshRenderer、Sprite、Label、Graphics、Mask、RichText、UIStaticBatch )
设置节点的Layer层级;
当节点设置的 Layer 属性包含在相机的 Visibility 属性 中时,节点便可以被相机看见,同时支持 3D 组件与 2D 组件的混合渲染。以便更灵活地控制节点组件的可见性,使分组显示多样化。
与Unity类似 。位置 、 旋转 、缩放
对于 UI的节点来说,因为 Creator 3.0 的 UI 节点需要其任意上级节点至少得有一个含有 UITransform 组件,在创建时若不符合规则,便会自动添加一个 Canvas 节点作为它的父级,所以上图中的节点树便将 UI 节点都统一放在了 Canvas 节点下。然后根据类别分别创建父节点,并将同类节点放在一个父节点下,从而构建出的节点树。
多层次细节(Level Of Details 以下简称 LOD)是大场景开发中常用的一种优化方式。LOD 的核心在于对于远处或者不重要的物体,降低其显示细节,以达到提升渲染效率的目的。
通常的 LOD 的做法是对于某些离屏幕较远或者不重要的物体,使用低模进行代替。
在引擎中,如果要启用 LOD,可以在 属性检查器 内选择 添加组件 按钮并选择 LOD Group 组件
LOD2 低模型、LOD丰富
resources.load("resources\images\shop_figure",SpriteFrame,()=>{
console.log("shop_figure.png loaded");
});
// 参数列表:资源路径 类型 加载成功的回调
为了减少下载的延迟,assetManager 和 Asset Bundle 中不但提供了加载资源的接口,每一个加载接口还提供了对应的预加载版本。开发者可在游戏中进行预加载工作,然后在真正需要时完成加载。预加载只会下载必要的资源,**不会进行反序列化和初始化工作,**所以性能消耗更小,适合在游戏过程中使用。
start () {
resources.preload('images/background/spriteFrame', SpriteFrame);
setTimeOut(this.loadAsset.bind(this), 10000);
}
loadAsset () {
resources.load('images/background/spriteFrame', SpriteFrame, (err, asset) => {
this.getComponent(Sprite).spriteFrame = asset;
});
}
开发者可以将自己的场景、资源、代码划分成多个 Asset Bundle,并在运行时动态加载资源,从而实现资源的模块化,以便在需要时加载对应资源.
Creator 还提供了引用计数机制来帮助开发者控制资源的引用和释放。例如:
resources.load('textures/armor/texture', Texture2D, function (err, texture) {
texture.addRef();
this.texture = texture;
});
//当不再需要持有该资源时,请调用 decRef 来减少引用,decRef 还将根据引用计数尝试自动释放
this.texture.decRef();
this.texture = null;
// 获取某个资源的缓存
assetManager.cacheManager.getCache('http://example.com/bundle1/import/9a/9aswe123-dsqw-12xe-123xqawe12.json');
// 清除某个资源的缓存
assetManager.cacheManager.removeCache('http://example.com/bundle1/import/9a/9aswe123-dsqw-12xe-123xqawe12.json');
渲染远距离物体时,mipmap 贴图比原图小,提高了显卡采样过程中的缓存命中率,所以渲染的速度得到了提升。同时因为 mipmap 的小图精度较低,从而减少了摩尔纹现象,可以减少画面上的锯齿。另外因为额外生成了一些小图,所以 mipmap 需要额外占用约三分之一的内存空间。
resources.load("testAssets/image/texture", Texture2D, (err: any, texture: Texture2D) => {
const spriteFrame = new SpriteFrame();
spriteFrame.texture = texture;
this.node.getComponent(Sprite).spriteFrame = spriteFrame;
});
如果引擎开启了 动态合图 功能,动态合图会自动将合适的贴图在开始场景时动态合并到一张大图上来减少 Drawcall。但是将贴图合并到大图中会修改原始贴图的 UV 坐标,如果在自定义 effect 中使用了贴图的 UV 坐标,这时 effect 中的 UV 计算将会出错,需要将贴图的 Packable 属性设置为 false 来避免贴图被打包到动态合图中。
使用resources目录下资源加载,
const url = 'test_assets/test_atlas/content/spriteFrame';
resources.load(url, SpriteFrame, (err: any, spriteFrame) => {
const sprite = this.getComponent(Sprite);
sprite.spriteFrame = spriteFrame;
});
//存在服务器上资源动态加载
const self = this;
const url = 'test_assets/test_atlas/content';
resources.load(url, ImageAsset, (err: any, imageAsset) => {
const sprite = this.getComponent(Sprite);
sprite.spriteFrame = SpriteFrame.createWithImage(imageAsset);
});
//-----
const self = this;
const url = 'test_assets/test_atlas/content';
resources.load(url, ImageAsset, (err: any, imageAsset) => {
const sprite = this.getComponent(Sprite);
const spriteFrame = new SpriteFrame();
const tex = new Texture2D();
tex.image = imageAsset;
spriteFrame.texture = tex;
sprite.spriteFrame = spriteFrame;
});
spriteFrame -> texture -> img
创建自动图集资源
let comp = this.getComponent('sp.Skeleton') as sp.Skeleton;
let image = "http://localhost/download/spineres/1/1.png";
let ske = "http://localhost/download/spineres/1/1.skel";
let atlas = "http://localhost/download/spineres/1/1.atlas";
assetManager.loadAny([{ url: atlas, ext: '.txt' }, { url: ske, ext: '.bin' }], (error, assets) => {
assetManager.loadRemote(image, (error, texture: Texture2D) => {
let asset = new sp.SkeletonData();
asset._nativeAsset = assets[1];
asset.atlasText = assets[0];
asset.textures = [texture];
asset.textureNames = ['1.png'];
asset._uuid = ske; // 可以传入任意字符串,但不能为空
asset._nativeURL = ske; // 传入一个二进制路径用作 initSkeleton 时的 filePath 参数使用
comp.skeletonData = asset;
let ani = comp.setAnimation(0, 'walk', true);
});
});
Creator 支持使用 Json 文件,通过 资源导入 的方式将其导入到编辑器,所有的 JSON 文件都会导入为 cc.JsonAsset 格式的资源。
开发者可通过 编辑器挂载 和 代码中动态加载 两种方式获取 Json 数据。
import { _decorator, Component, JsonAsset } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('ItemTemplate')
export class ItemTemplate extends Component {
// 声明属性 ‘itemGiftJson‘ 的类型为 JsonAsset
@property(JsonAsset)
itemGiftJson: JsonAsset = null!;
start () {
// 获取到 Json 数据
const jsonData: object = this.itemGiftJson.json!;
}
}
import { _decorator, Component, JsonAsset, resources, error } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('ItemTemplate')
export class ItemTemplate extends Component {
start () {
resources.load('gameGiftJson', (err: any, res: JsonAsset) => {
if (err) {
error(err.message || err);
return;
}
// 获取到 Json 数据
const jsonData: object = res.json!;
})
}
}