【Cocos Creator 踩坑笔记】如何用代码动态读取资源

最近项目需要,研究 Cocos Crater 的使用,初次使用还是踩了挺多坑的,解决之后,特此记录一下。

首先资源文件要放在 resources 文件夹下,然后使用 cc.resources.load 函数来进行资源加载。

cc.resources.load(path, type, onComplete:()=>void);

下面是一段代码示例:

cc.resources.load("music/bgm", cc.AudioClip, (err, clip :cc.AudioClip)=>{
	if (err) {
        cc.error(`AudioClip load error : ${err}`);
        return;
    }
    clip.addref();
    // clip 就是已经加载好的 AudioClip 资源
    // To do something with clip
});

在最开始使用这个函数的时候,踩了一个挺烦人的坑,记录一下。


我获取了某节点上的 AudioSource 组件(即 this.audiosource 变量), 我希望读取 resources/music 文件夹下的 bgm.ogg 文件,设置为 this.audiosourceclip ,然后播放。

我尝试了下面几种写法(以下三种写法都是错误示范)。

写法一:
let mClip : cc.AudioClip = null;
cc.resources.load("music/bgm", cc.AudioClip, (err, clip)=>{
	if (err) {
        cc.error(`AudioClip load error : ${err}`);
        return;
    }
    clip.addref();
	mClip = clip;
});
this.audiosource.clip = mClip;
this.audiosource.play();

运行结果是失败的。

断点调试时发现,程序先执行了第 10 行的赋值语句,再执行第 8 行的赋值语句,所以给 this.audiosource.clip 赋值时 mClip 值仍为 null

写法二:

我将代码拆分开来,读取资源先执行,给 this.audiosource.clip 赋值通过调用其他函数来执行,mClip 声明为类的成员变量。

//声明一个成员变量 mClip 用来记录 clip 的值
private mClip : cc.AudioClip = null;
cc.resources.load("music/bgm", cc.AudioClip, (err, clip)=>{
	if (err) {
        cc.error(`AudioClip load error : ${err}`);
        return;
    }
    clip.addref();
	this.mClip = clip;
});
this.audiosource.clip = this.mClip;
this.audiosource.play();

运行结果是失败的。

断点调试发现,在第二块代码中,this.mClip 确实已经赋值成功,但是在第三块代码调用的时候,this.mClip 值仍为 null

写法三:
cc.resources.load("music/bgm", cc.AudioClip, (err, clip)=>{
	if (err) {
        cc.error(`AudioClip load error : ${err}`);
        return;
    }
    clip.addref();
    this.audiosource.clip = clip;
    this.audiosource.play();
});

既然 clip 的值传不出来,我决定尝试直接在加载资源的函数里为 this.audiosource.clip 赋值。

运行结果是失败的。

经过断点调试发现 clip 值是正常的,但是 this.audiosourcenull

上述是我进行资源读取的尝试过程。

当然代码是有问题的,因为结果都是失败的。

如果你能看出来上面的代码问题出在哪儿,那么恭喜你,成功跳过了这个坑。如果你也遇到了同样的问题,那么继续看,一起填坑吧。


下面是错误原因分析及正确写法:

核心原因是:资源加载时异步的。

第一种写法失败的原因。第 8 行的代码是资源加载成功后执行的,而由于异步加载,第 10 行代码是直接执行的(不会因为等待加载资源而阻塞),所以执行顺序是反过来的。

第二、三种写法失败的原因,是在于 this 指针。由于异步加载,在 onCompleted 执行时,this 指向的对象,其实跟 this.audiosource 这里的 this 指向的对象不是同一个。

let self = this;
cc.resources.load("music/bgm", cc.AudioClip, (err, clip)=>{
	if (err) {
        cc.error(`AudioClip load error : ${err}`);
        return;
    }
    clip.addref();
    self.audiosource.clip = clip;
    self.audiosource.play();
});

解决方法,使用一个临时变量 self 来记录 this 指向的对象就可以了,如上代码所示。


2020.12.14 更新
随着学习的深入,我发现是我想复杂了,其实还有最简单的一种方法。
就是回调函数的 .bind(this) 函数。示例代码如下

//调用回调函数时,使用 .bind(this) 可以绑定当前对象
cc.resources.load("music/bgm", cc.AudioClip, _callback.bind(this));
//使用 bind(this) 之后,回调函数中可以正常使用 this 对象了
_callback(err, clip) : void {
	if (err) {
        cc.error(`AudioClip load error : ${err}`);
        return;
    }
    clip.addref();
	this.audiosource.clip = mClip;
	this.audiosource.play();
}
### 回答1: Cocos Creator是一个流行的游戏开发引擎,提供了各种功能和工具,可以帮助开发者快速创建和设计小游戏。当我们提到Cocos Creator小游戏源代码时,通常是指游戏的源代码文件和资源文件。 Cocos Creator的源代码文件由JavaScript编写,通常包括游戏的逻辑、场景组织和界面展示等方面的代码。开发者可以通过编辑源代码来修改游戏的行为,添加新的功能或调整游戏的操作方式。通过理解源代码,开发者可以深入了解游戏的工作原理和内部机制。 此外,Cocos Creator的源代码还包括资源文件,如图像、声音和动画等。这些资源文件是游戏中使用的各种元素,可以通过编辑软件进行设计和修改。通过修改资源文件,开发者可以改变游戏的外观和音效,增加游戏的吸引力和乐趣。 如果我们拥有Cocos Creator小游戏的源代码,我们可以根据自己的需求进行定制和修改,使游戏更符合自己的创意和目标。我们可以通过学习源代码来了解游戏的设计理念和技巧,从而提高自己的游戏开发能力。 总而言之,Cocos Creator小游戏源代码是游戏开发过程中的重要组成部分,通过对源代码的理解和修改,我们可以定制和优化游戏,使其更具个性和品质。 ### 回答2: Cocos Creator 是一款用于开发2D和3D游戏的游戏引擎。它是基于 Cocos2d-x 引擎的基础上进行开发的,同时支持 JavaScript 和 TypeScript 编程语言。使用 Cocos Creator 可以方便地创建各种类型的小游戏。 Cocos Creator 的小游戏源代码是指使用 Cocos Creator 编写的游戏的源代码。这些源代码包含了游戏的各种各样的功能和逻辑,例如游戏场景的创建、角色控制和碰撞检测等。 在 Cocos Creator 的小游戏源代码中,你可以看到许多不同的文件。其中最重要的是场景文件,它包含了游戏中的场景布局和对象的放置。另外还有脚本文件,用于编写游戏的逻辑和功能。以及资源文件,包括游戏中使用的图片、音效和动画等。 小游戏源代码中的脚本文件是游戏的核心部分,通过编写脚本可以实现游戏中的各种功能。你可以在脚本中定义角色的移动方式、敌人的行为模式、背景音乐的播放等。同时,你还可以使用脚本文件进行碰撞检测、游戏得分的计算和关卡的切换等。 总而言之,Cocos Creator 的小游戏源代码提供了游戏的各种功能和逻辑的实现方式。通过学习和理解这些源代码,你可以自由地修改和扩展游戏的功能,以满足自己的需求。同时,你也可以参考源代码中的编程方式和设计思路,来进行自己的游戏开发。 ### 回答3: Cocos Creator是一款用于开发小型游戏的游戏引擎和开发工具。它提供了适用于多平台的跨平台开发功能,以及强大的编辑器和场景编辑工具。 Cocos Creator使用JavaScript脚本语言编写游戏逻辑,并使用C++编写引擎核心功能。游戏内容可以在编辑器中创建和编辑,然后通过编译输出为可在多个平台上运行的游戏代码Cocos Creator的游戏源代码包括引擎核心的C++部分以及游戏逻辑的JavaScript脚本代码。引擎核心代码的作用是提供游戏开发所需的基础功能,包括图形渲染、物理碰撞检测、动画控制和资源管理等。 在游戏源代码中,开发者可以编写游戏逻辑的JavaScript脚本,包括角色移动、碰撞检测、游戏进度控制等。开发者可以通过编辑器添加场景、角色和其他游戏资源,并使用JavaScript脚本将它们连接起来,实现游戏的逻辑和交互。 通过编写自定义的脚本代码,开发者可以为游戏增加各种功能和特效,比如实现角色的特殊能力、设计游戏关卡的难度、添加音效和动画效果等。 总的来说,Cocos Creator小游戏源代码包含了游戏引擎的核心和游戏逻辑的脚本代码,开发者可以利用这些代码来创建和定制自己的小型游戏。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

机灵鹤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值