Request by sending an email to developer@vatom.com
To register a custom avatar, call user.registerAvatar(), specifying the name, model URL, etc of the avatar. You also need to specify a type
, which represents the avatar's skeletal structure and how the app should animate the avatar model.
this.user.registerAvatar({
id: 'com.myplugin.John',
name: 'John',
type: 'humanoid',
imageURL: this.paths.absolute('john-preview.jpg'),
properties: {
url: this.paths.absolute('john.glb')
}
})
Once an avatar is registered, the user will be able to select it in the Profile -> Select Avatar menu.
The type
field used when registering an avatar represents the skeletal structure of the avatar, which affects how animations are applied to the avatar. There are two types used in the app by default, however plugins are free to create their own custom avatar types as well.
'static'
This is the most basic type of avatar. No dynamic animations are applied to the avatar at all, and it simply plays whatever animation (if any) is specified in the properties
field. The model will also be automatically rotated to face the direction the user is moving.
'humanoid'
This is a preset avatar type that the app supports by default. The app includes preset animations for idle, walk, run etc, which are played and blended dynamically. The skeleton structure and face morphs are the same as used by readyplayer.me's full-body avatars.
If you specify anything else for the type
field, a new avatar type will be defined. This is similar to using 'humanoid'
but no builtin animations will exist, meaning you have to supply them yourself inside the model's GLB file. Each animation name must follow the format of <type>.<action>
, for example if your avatar's type is snake
the walk animation must be called snake.walk
. The animations which must be included are:
Action | Description |
---|---|
idle | Played on a loop when the user isn't moving. |
walk | Played while the user is moving slowly. Blended smoothly with idle until the user's speed reaches the avatar's walking speed. |
run | Played while the user is moving quickly. Blended smoothly with walk until the user's speed reaches the avatar's running speed. |
lookdown | A single-frame animation used to move the avatar's head downwards. This is blended based on how much the app wants to move the avatar's head downwards. |
lookup | Same as above |
lookleft | Same as above |
lookright | Same as above |
jump | Played at the start of a jump animation. The last frame is paused until the user hits the ground again. Note that the user begins moving upwards immediately at the same time this starts playing. |
land | Played after jump once the user hits the ground. Animation duration should be 1 second. |
For all avatar types except 'static'
, the app will look for certain named morphs inside the model GLB for controlling face movements. If you want the avatar to have dynamic face movements, the avatar model must include these named morphs:
Morph | Description |
---|---|
eyeBlinkLeft , eyeBlinkRight | Controls eye blink. |
eyeLookDownLeft , eyeLookInLeft , eyeLookOutLeft , eyeLookUpLeft | Controls left eye movement. |
eyeLookDownRight , eyeLookInRight , eyeLookOutRight , eyeLookUpRight | Controls right eye movement. |
viseme_CH , viseme_DD , viseme_E , viseme_FF , viseme_I , ``viseme_O, viseme_PP, viseme_RR, viseme_SS, viseme_TH, viseme_U, viseme_aa, viseme_kk, viseme_nn, viseme_sil` | Used for lip syncing. |
mouthSmile , mouthOpen , mouthClose , mouthPucker , browDownLeft , browDownRight , browInnerUp , browOuterUpLeft , browOuterUpRight | Used for facial expressions. |
Note that more morphs may be used as well. See the reference model here for all face morphs.
Plugins can also override the default avatar animations and provide their own animations. These animations can be applied to any avatar type, even avatars registered by other plugins. Animation names are automatically prefixed by the current user's avatar type, so it's possible to create different animations for different skeleton types, and not have to worry about which one is selected when playing the animation.
For example, a plugin could create a new 'sit'
animation, for both the default 'humanoid'
avatar and a new 'quadruped'
avatar. Then any plugin can simply play the 'sit'
animation, and it'll play regardless of if the user is a 'humanoid'
or a 'quadruped'
.
// Called on plugin load
onLoad() {
// Register a custom dog avatar
this.user.registerAvatar({
id: 'com.myplugin.Spot',
name: 'Spot',
type: 'quadruped',
imageURL: this.paths.absolute('spot.jpg'),
properties: {
url: this.paths.absolute('spot.glb')
}
})
// Register 'humanoid' sit animations ... this file contains 'humanoid.sit_start', 'humanoid.sit_loop', and 'humanoid.sit_end'
this.objects.registerAnimations(this.paths.absolute('animations-humanoid.glb'))
// Register 'quadruped' sit animations ... this file contains 'quadruped.sit_start', 'quadruped.sit_loop', and 'quadruped.sit_end'
this.objects.registerAnimations(this.paths.absolute('animations-quadruped.glb'))
// Register a menu button on the action bar
this.menus.register({
icon: this.paths.absolute('sit-icon.png'),
text: 'Sit',
action: () => this.sitNow()
})
}
// Called when the user presses the Sit button
sitNow() {
// Override the avatar animation ... note how we don't include the 'humanoid.' animation name prefixes.
// The app will determine the prefix based on the user's current avatar type.
this.user.overrideAvatarAnimation({
animation_start: 'sit_start',
animation: 'sit_loop',
animation_end: 'sit_end',
loop: true,
fixed_movement: { x: 0, y: 0, z: 0 }
})
}