Client Animation System
From Multiverse
| Client Scripting |
|
Overview • Coordinated Effects • Fireball Example • Terrain Decals • Compositors • About Shadows • Client Animation System • Creating Your Own Animations • Scripting Avatar Appearance |
| Reference |
Contents |
Overview
The Multiverse servers maintain and adjust information relevant to gameplay (such as reducing the health of a mob when a player executes an attack), but the Client handles matters that have immediate visual or audible effects, for example playing an attack animation and the sound of the player's sword hitting armor. Object properties communicate state from the server to the client, and then scripts running on the Client determine which animations to play based on the value of these properties and other Client state such as whether the player is moving.
The sample animation script /Scripts/ClientAnimations.py provides an example of using the Client animation system. To add animation functionality to your world, modify, extend or completely rewrite this script to meet your needs.
See also Creating Your Own Animations.
Adding client animation scripting to your world
In the 1.0 Sampleworld asset repository, Client animation scripting is enabled by default.
Otherwise, to add client animation scripting to your world:
- Add the
/Scripts/ClientAnimations.pyfrom Sampleworld to your asset repository. This script is an example of using client animations. Modify, extend, or completely rewrite the script for your world. - Make sure the following line is in your Client Startup Script
Startup.py:
import ClientAnimations
This Startup.py in the Sampleworld asset repository includes this line by default.
Client animations script
The Sampleworld asset repository contains an example of an animation script, /Scripts/ClientAnimations.py for you to modify and extend for your world.
The script sets up event handler methods called when WorldObjects are added and removed from the scene. When a WorldObject is added to the scene, if it is an NPC or player, these event handlers create an object to hold the state for animations. The script also adds event handlers to the WorldObject to track position, movement speed, and object property changes. The event handlers update the state variables used to determine which animation to play, and then they play whichever animation is required.
Example animations
The example client animation script defines the following animations:
- Idle animations: Standard idle, combat idle, dead, dance
- Move animations: walk and run. If you set the mob's 'runThreshold' property, then it will play the walk animation when it moves slower than that speed, and the run animation when it moves faster.
The following table describes the animations. In the table, "mob" refers to the WorldObject in question, generally a mob or player avatar.
| Name | Animation Name Property | Description | Can loop? | Default Animation Name |
|---|---|---|---|---|
| Standard idle | idleAnimName | One of:
| Yes | 'idle' |
| Combat idle | combatIdleAnimName | Plays when the mob's Combat property is true. | Yes | 'combat_idle' |
| Dance | danceAnimName | Plays when the mob's Dance property is true. | Yes | 'dance' |
| Death | deathAnimName | Plays when the mob's Dead property is true. | No | 'death' |
| Walking | walkAnimName | Plays when a moving mob's speed is less than the run threshold. | Yes | 'walk' |
| Running | runAnimName | Plays when a moving mob's speed is greater than or equal to the run threshold. | Yes | 'run' |
Run threshold
The run threshold is the speed above which the run animation plays for a mob or character. The runThreshold property affects which animation is played by the sample client animation script when the character moves. If the movement speed is less than runThreshold, then the walk animation is played. If it is greater than runThreshold, then the run animation is played.
To set the run threshold for a mob, add the following code to config/worldname/templates.py:
tmpl.put(WorldManagerClient.NAMESPACE, WorldManagerClient.TEMPL_RUN_THRESHOLD, Float(speed))
where tmpl is the Template object for the mob, and speed is the run threshold speed, in mm/sec.
Set the run threshold for a character in config/worldname/character_factory.py as follows:
player.put(WorldManagerClient.NAMESPACE, WorldManagerClient.TEMPL_RUN_THRESHOLD, Float(5000))
NOTE: To change the run threshold value for a character, you must create a new character because character_factory.py is only used to create new characters. Existing characters are saved and stored in the database.
Construtor
The constructor initializes all the properties and sets the idle animation to
- 'idle', if it is a defined animation.
- 'idle_01', if it is a defined animation.
- None, if neither is defined.
Properties
The example client animation script defines the following properties. Add or modify these properties to suit your world.
| Property | Type | Description | Default Value |
|---|---|---|---|
| Dead | Boolean | Whether NPC or player is dead. | False |
| Dance | Boolean | Whether NPC or player is dancing. | False |
| Combat | Boolean | Whether NPC or player is in combat state. | False |
| MovementSpeed | Floating point | Current movement speed. | 0.0 |
| Moving | Boolean | Whether NPC or player is moving | False |
| CurrentIdleAnim | String | Name of current idle animation | 'idle' |
| LoopIdle | Boolean | Whether to loop the idle animation. | True |
| CurrentMoveAnim | String | Name of current move animation. | 'run' |
| LoopMove | Boolean | Whether to loop the move animation | True |
| PlayingAnim | String | Name of current animation playing. | None |
| AnimOverride | Boolean | Whether to override the client animation system to play a coordinated effect. | False |
| runSound | String | Name of sound to play in run state. Note that this is for any movement speed. | None |
| walkAnimName | String | Name of animation to play in walk state. | 'walk' |
| runAnimName | String | Name of animation to play in run state. | 'run' |
| idleAnimName | String | Name of idle animation. | 'idle' |
| deathAnimName | String | Name of death animation. | 'death' |
| danceAnimName | String | Name of dance animation. | 'dance' |
| combatIdleAnimName | String | Name of combat idle animation. | 'combat_idle' |
Methods
- Dispose(): Turns off the run sound, if it is playing. Called when the mob is unloaded from the system.
- DirectionChangeHandler(): Event handler called when the mob's direction changes.
- setIdleAnim(): Set the idle animation to the specified name (String).
- setMoveAnim(): Set move animation to the specified animation name (String).
- playAnim(): As long as client animation override is not in effect, play the appropriate animation:
- Move animation if moving
- Idle animation if not moving
- updateIdleAnim(): Set the idle animation based on the mob's state:
- Dead animation if mob is dead.
- Combat Idle animation if mob is in combat state.
- Standard idle animation, otherwise.
- updateMoveAnim(): Set the move animation based on the mob's state:
- Run animation if mob is moving faster than the run threshold, or if the run threshold is not defined.
- Walk animation if mob is moving slower than the run threshold, if defind.
- setDead(): Set the mob's
Deadproperty based on the value of the specifiedWorldObjectproperty. - setDance(): Set the mob's
Danceproperty based on the value of the specifiedWorldObjectproperty. - setCombat(): Set the mob's
Combatstate based on the value of the specifiedWorldObjectproperty. - setAnimOverride(): Call with True to temporarily hand over control of animations to a coordinated effect script. Call with False to return control to the client animation system. For example:
caster.SetProperty('client.animationoverride', True)
- setSpeed(): Switches between move animations and idle animations. Depending on the mob's speed, either plays:
- The appropriate move animation and the run sound.
- The appropriate idle animation.
Client animation scripting versus coordinated effects
If you use the framework provided by the sample scripts, follow these guidelines:
- Use client animation scripting to create animations based on some object state that loop repeatedly until the state changes (for example movement states such as running, walking, swimming, flying and "idle" type states such as idle, combat idle, death, dancing.
- Use coordinated effects with the animation override mechanism (setting
client.animationoverrideobject property) to create animations that are played once as part of an effect or emote (for example, wave, laugh, attack, or cast spell).
How to play a coordinated effect
The client animation script enables a coordinated effect script to take control of animation for a particular world object, playing the animations for the effect, and then releasing control so that the client animation script can return the world object to whatever its current looping animation should be.
To handoff control to a coordinated effect, call:
mob.SetProperty('client.animationoverride', True)
Where mob is the WorldObject for which you want to play the coordinated effect. After playing the cooridnated effect animation, return control to the client anmiation system with:
mob.SetProperty('client.animationoverride', False)
The client animation script watches for changes to the property "client.animationoverride", and while this property is set to "True", it will not play any animations. When the value changes to "False", the script play the current looping animation.
See Creating Your Own Animations for more information.
Example
The Sampleworld asset repository includes a coordinated effect script for a simple attack, /Scripts/AttackEffect.py, that uses the animation override feature to coordinate playing of animations with the client animation script. This effect script plays the attack animation and a sound of a sword hitting armor.
caster.SetProperty('client.animationoverride', True)
caster.QueueAnimation("attack")
# wait for the duration of the animation to turn off the animation override
yield int(caster.Model.AnimationLength(animName) * 1000)
caster.SetProperty('client.animationoverride', False)
