终点胜利
当玩家到达闯关小游戏的终点时,我们需要给出一些游戏反馈。本节课我们将学习使用动画、特效、音效来完成游戏中各个环节的反馈。
1.预览资源
下面给大家介绍动画、特效、音效这3个资源的预览方式。
预览动画
①在美术资源中选中“动画”
②点击动画资源右上角的放大镜图标
③在弹出的窗口中,点击播放按钮即可预览动画
④如果需要这个动画,就记录下它的AssetID
预览特效
预览特效的方式和预览动画相似,也是需要点击资源右上角的放大镜来进行预览。
预览音效
①在美术资源中选中“音效”
②点击音效资源右上角的放大镜图标
③在弹出的窗口中,点击播放按钮即可预览音效
④如果需要这个音效,就记录下它的 AssetID
在这里列出本节课程中所用到的资源的 AssetID:
进入检查点触发的特效:【89097】
进入检查点触发的音效:【38193】
进入终点触发的特效:【142750】
进入终点触发的音效:【47425】
进入终点播放的动画:【14509】
死亡时播放的特效:【27421】
死亡时播放的音效:【120841】
提示
大家有可能通过上面提供的AssetID搜索不到对应的资源,那么有可能是因为资源被下架了,大家重新挑选一个自己喜欢的特效进行替换即可。
2.资源加载
这里的资源加载具有两个含义,分别是下载编辑器资源以及加载游戏资源。
下载编辑器资源:
我们下载口袋方舟编辑器,是不会将资源库中的美术资源全部下载下来的,资源库的资源只有在我们需要使用的时候才会去进行下载。所以当我们第一次将资源拖动到场景上的时候,资源需要一个短暂的时间进行下载,下载过后再使用就不会卡顿了。
加载游戏资源:
我们的游戏在运行的时候也需要去加载各种美术资源,如果资源没有经过加载,那么使用代码去动态创建资源的时候,就会导致创建速度变慢。
加载游戏资源的方式主要有3种:
方式一:将资源直接拖动到场景中。
方式二:将资源拖动到优先加载中。
方式三:使用AssetUtil.asyncDownloadAsset这个API来下载资源
下图展示了使用优先加载的方式来加载游戏资源
①在搜索框输入资源的AssetID来进行资源查找
②将找到的资源拖动到优先加载下
3.终点&检查点 反馈
终点其实就是特殊的检查点,所以我们只需要在检查点脚本中添加反馈逻辑即可。
添加完反馈逻辑的CheckPointTrigger脚本内容如下:
该脚本有如下几个要点:
①添加了对pointNumber的判断,当pointNumber为-1时,代表终点
②通过loadAnimation进行动画播放
③通过EffectService.playAtPosition进行特效播放
④通过SoundService.playSound进行音效播放
ts
@Component
export default class CheckPointTrigger extends Script {
@Property({ displayName: "序号" })
public pointNumber: number = 0
/** 当脚本被实例后,会在第一帧更新前调用此函数 */
protected onStart(): void {
let trigger = this.gameObject as Trigger
trigger.onEnter.add((other: GameObject) => {
// 进入的物体是否是角色
if (other instanceof Character) {
// 进入的角色 是否是 当前客户端角色
if (other == Player.localPlayer.character) {
// 本地事件通信(派发)
Event.dispatchToLocal("CheckPoint", this)
// 播放特效
EffectService.playAtPosition("89097", this.gameObject.worldTransform.position)
// 播放音效
SoundService.playSound("38193")
}
// 如果关卡号为-1,代表终点
if (this.pointNumber == -1) {
// 播放动作
other.loadAnimation("14509").play()
// 播放特效
EffectService.playAtPosition("142750", this.gameObject.worldTransform.position)
// 播放音效
SoundService.playSound("47425")
}
}
})
}
}
@Component
export default class CheckPointTrigger extends Script {
@Property({ displayName: "序号" })
public pointNumber: number = 0
/** 当脚本被实例后,会在第一帧更新前调用此函数 */
protected onStart(): void {
let trigger = this.gameObject as Trigger
trigger.onEnter.add((other: GameObject) => {
// 进入的物体是否是角色
if (other instanceof Character) {
// 进入的角色 是否是 当前客户端角色
if (other == Player.localPlayer.character) {
// 本地事件通信(派发)
Event.dispatchToLocal("CheckPoint", this)
// 播放特效
EffectService.playAtPosition("89097", this.gameObject.worldTransform.position)
// 播放音效
SoundService.playSound("38193")
}
// 如果关卡号为-1,代表终点
if (this.pointNumber == -1) {
// 播放动作
other.loadAnimation("14509").play()
// 播放特效
EffectService.playAtPosition("142750", this.gameObject.worldTransform.position)
// 播放音效
SoundService.playSound("47425")
}
}
})
}
}
4.死亡反馈
角色死亡的逻辑是编写在关卡管理器脚本中的,所以我们需要在关卡管理器中编写死亡反馈逻辑。
添加完反馈逻辑的 LevelManager脚本 内容如下:
ts
import CheckPointTrigger from "./CheckPointTrigger"
/**
* 关卡管理器
*/
export class LevelManager{
// 单例模式
private static _instacne:LevelManager
public static get instance():LevelManager{
if(LevelManager._instacne==null){
LevelManager._instacne = new LevelManager()
}
return LevelManager._instacne
}
/**死亡触发器 */
private _deathTrigger:Trigger
/**复活位置 */
private _rebornPosition:Vector = new Vector(10,0,420)
public async init(){
this._deathTrigger = await GameObject.asyncFindGameObjectById("299CDDA6") as Trigger
this._deathTrigger.onEnter.add((other:GameObject)=>{
// 当进入的物体是角色类型
if(other instanceof Character){
// 让角色死亡
this.charDeath(other)
}
})
Event.addLocalListener("CheckPoint",(checkPointTrigger:CheckPointTrigger)=>{
this._rebornPosition = checkPointTrigger.gameObject.worldTransform.position.clone()
})
}
/**让角色死亡 */
public charDeath(char:Character){
// 开启布娃娃属性
char.ragdollEnabled = true
// 播放特效
EffectService.playAtPosition("27421",char.worldTransform.position)
// 播放音效
SoundService.playSound("120841")
setTimeout(() => {
// 让角色复活
this.charReborn(char)
}, 3000);
}
/**让角色复活 */
public charReborn(char:Character){
if(char == Player.localPlayer.character){
// 将角色的位置改变到复活点
char.worldTransform.position = this._rebornPosition.clone()
}
// 关闭布娃娃属性
char.ragdollEnabled = false
}
}
import CheckPointTrigger from "./CheckPointTrigger"
/**
* 关卡管理器
*/
export class LevelManager{
// 单例模式
private static _instacne:LevelManager
public static get instance():LevelManager{
if(LevelManager._instacne==null){
LevelManager._instacne = new LevelManager()
}
return LevelManager._instacne
}
/**死亡触发器 */
private _deathTrigger:Trigger
/**复活位置 */
private _rebornPosition:Vector = new Vector(10,0,420)
public async init(){
this._deathTrigger = await GameObject.asyncFindGameObjectById("299CDDA6") as Trigger
this._deathTrigger.onEnter.add((other:GameObject)=>{
// 当进入的物体是角色类型
if(other instanceof Character){
// 让角色死亡
this.charDeath(other)
}
})
Event.addLocalListener("CheckPoint",(checkPointTrigger:CheckPointTrigger)=>{
this._rebornPosition = checkPointTrigger.gameObject.worldTransform.position.clone()
})
}
/**让角色死亡 */
public charDeath(char:Character){
// 开启布娃娃属性
char.ragdollEnabled = true
// 播放特效
EffectService.playAtPosition("27421",char.worldTransform.position)
// 播放音效
SoundService.playSound("120841")
setTimeout(() => {
// 让角色复活
this.charReborn(char)
}, 3000);
}
/**让角色复活 */
public charReborn(char:Character){
if(char == Player.localPlayer.character){
// 将角色的位置改变到复活点
char.worldTransform.position = this._rebornPosition.clone()
}
// 关闭布娃娃属性
char.ragdollEnabled = false
}
}