头像动画
让玩家的头像播放默认或自定义动画,并检测某个表情动作何时结束
你可以在场景代码中让玩家执行动画。这有助于增强沉浸感,也能帮助玩家之间互相传达其他人在做什么。角色动画会同时被该玩家(第三人称视角)以及周围的其他玩家看到。
由玩家控制、作用于全身的动画会被默认的移动动画覆盖,例如行走和跳跃。因此,由场景播放的全身动画只会在玩家静止站立时播放。如果玩家行走或跳跃,任何全身动画都会被中断。上半身动画不会因移动而中断。
使用场景编辑器
让玩家执行动画的最简单方法是使用场景编辑器。使用无代码 播放表情动作 操作来播放默认动画,或使用 播放自定义表情动作 操作来播放文件中的动画。参见 让任意项目变为智能项目.
默认动画
使用 triggerEmote() 函数来运行玩家可以在 Decentraland 中随时播放的某个默认动画。此函数接受一个具有以下属性的对象作为参数:
predefinedEmote:现有表情动作的字符串名称。mask: (可选)使用AvatarMask枚举中的值。比如,AvatarMask.AM_UPPER_BODY只会让角色的上半身执行动画。参见 仅动画化上半身.
import { triggerEmote } from '~system/RestrictedActions'
const emoter = engine.addEntity()
Transform.create(emoter, { position: Vector3.create(8, 0, 8) })
MeshRenderer.setBox(emoter)
MeshCollider.setBox(emoter)
pointerEventsSystem.onPointerDown(
{
entity: emoter,
opts: { button: InputAction.IA_POINTER, hoverText: '跳舞' },
},
() => {
triggerEmote({ predefinedEmote: 'robot' })
}
)下面这些表情动作会在你的场景中反馈玩家的动作,以下内容都可作为 predefinedEmote 字段的有效值:
buttonDownbuttonFrontgetHitknockOutleveropenChestopenDoorpunchpushswingWeaponOneHandswingWeaponTwoHandsthrowsittingChair1sittingChair2sittingGround1sittingGround2
这些表情动作对所有玩家都可在其默认表情轮盘中使用,也可以在任何场景中使用。
挥手fistpumprobotraiseHand鼓掌money亲吻tikhammertektonikdontseehandsairshrugdiscodabheadexplode
自定义动画
使用 triggerSceneEmote() 让玩家执行一个自定义动画,该动画以 .glb 文件形式存储为场景资源的一部分。
此函数接受一个具有以下属性的对象:
src:指向表情动作文件的路径字符串。loop:如果为 true,动画将持续循环,直到玩家移动或动画停止。默认为 false。mask: (可选)使用AvatarMask枚举中的值。比如,AvatarMask.AM_UPPER_BODY只会让角色的上半身执行动画。参见 仅动画化上半身.
仅动画化上半身
两者都满足 triggerEmote() 和 triggerSceneEmote() 接受一个可选的 mask 属性,用于将动画限制为头像身体的一部分。
通常,动画会在玩家一走动或一跳跃时立刻停止,因为默认的移动动画会接管整个身体。当你设置 mask 为 AvatarMask.AM_UPPER_BODY时,动画只会驱动角色腰部以上的部分,而腿部仍由默认的移动动画控制。这意味着玩家可以在上半身播放你的动画时继续在场景中行走或奔跑。将其用于不应中断移动的动作,例如搬运箱子、举着火把或抛接杂耍。
在这个示例中,玩家点击按钮后会开始举起双臂欢呼,并以循环动画播放。由于只动画化了上半身,他们在欢呼时仍可继续在场景中奔跑,例如追随赛跑或足球比赛中的进展。
需要注意以下几点:
AvatarMask.AM_UPPER_BODY目前是AvatarMask枚举中的唯一值。要播放全身动画,只需不要设置mask属性定义。该
loop该属性的行为与全身动画相同:当使用loop: false带掩码的动画会播放一次,然后上半身恢复为正常移动动画;而使用loop: true时,它会重复播放,直到停止。要从代码中停止循环的带掩码动画,请调用
stopEmote({}),它同样从~system/RestrictedActions.
检测表情何时结束
每个表情动作生命周期事件都会通过玩家实体上的 AvatarEmoteCommand 组件上报。每个新条目都带有一个 state 字段,其值来自 EmoteState 枚举中使用:
EmoteState.ES_STARTED:表情动作开始播放。当state字段缺失时(由较旧客户端写入的条目),报告的值也是如此。EmoteState.ES_FINISHED:一个非循环表情动作已自然播放结束。EmoteState.ES_INTERRUPTED:表情动作被提前中断:玩家移动或跳跃、传送、开始了另一个表情动作、明确停止了该表情动作,或者玩家离开了场景。
这适用于由场景触发的表情动作(triggerEmote() 和 triggerSceneEmote())以及玩家通过表情轮盘自己播放的表情动作,也适用于场景中其他玩家播放的表情动作。
使用 onChange 在……上的函数 AvatarEmoteCommand 组件来响应每个新条目:
最后更新于