APIDOCUMENTATION
GENERAL
Home
Testing Link
Vatom CLI
SPACES
Overview
Release notes

World Creation

Introduction
Creating Models
Importing Objects
Adjusting Looks
Scene Limitations
Health Monitor
Recommended external tools

Using Plugins

Media: Audio
Places
PLUGINS IN SPACES
Overview
Publishing
Support & Feedback

Guides

Creating a Plugin
Creating a Component
Custom Avatars

Building & Publishing

Examples

API Reference

Globals
Audio
Hooks
Menus
Messages
Objects
Paths
User
World
SMART NFT DESIGNS
Overview

Designs

Create a New NFT Design

Views

Create a New View
Developing Your View
Publishing a View
Change LogForum

Custom Avatars

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.

Register an avatar

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.

Skeleton types

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.

Type: '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.

Type: '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.

Type: Custom

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:

ActionDescription
idlePlayed on a loop when the user isn't moving.
walkPlayed while the user is moving slowly. Blended smoothly with idle until the user's speed reaches the avatar's walking speed.
runPlayed while the user is moving quickly. Blended smoothly with walk until the user's speed reaches the avatar's running speed.
lookdownA 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.
lookupSame as above
lookleftSame as above
lookrightSame as above
jumpPlayed 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.
landPlayed after jump once the user hits the ground. Animation duration should be 1 second.

Face Morphs

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:

MorphDescription
eyeBlinkLeft, eyeBlinkRightControls eye blink.
eyeLookDownLeft, eyeLookInLeft, eyeLookOutLeft, eyeLookUpLeftControls left eye movement.
eyeLookDownRight, eyeLookInRight, eyeLookOutRight, eyeLookUpRightControls 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, browOuterUpRightUsed for facial expressions.

Note that more morphs may be used as well. See the reference model here for all face morphs.

Custom Animations

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'.

Custom animation

// 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 }
    })
}