# Character System

This module is a high-level impementation of a character with 3rd-person camera (both player-controlled and NPC). It has configuration file in XML format.

The character can be split into the following parts:

• Physical model
• Visual appearance (skin)
• Animation tree
• Camera
• Controls
The most complicated task is an interconnection between the character logic and its animation logic.

## Character Logic

### Orientation There is a set of parameters describing orientation of a character in space:

• Position is a coordinates of the character in space
• Angle is an orientation of the character relatively to Z axis
• Yaw is an azimuth angle of aiming (from -180 to 180 degrees)
• Pitch is a zenith angle of aiming (from -180 to 180 degrees)

### Movement

There is a set of parameters describing movement of the character in space:

• Velocity is a velocity vector of the character
• Speed is a speed of the character in XOY plane
• SpeedZ is a vertical speed of the character
• RotationSpeed is a speed of Angle changing

During movement of the character in XOY plane its Angle is smoothly changed according to the direction of the movement.

If there is no movement, Angle will be changing if difference between Angle and Yaw is greater than a threshold value (turn_angle_threshold). Rotation will take place with turn_speed speed by turn_angle_threshold steps, so rotation angle will be always divisible by turn_angle_threshold (you can use this fact to create a good-looking animation of in-place turns).

### States

There is a set of built-in states of the character.

MoveState:

• MOVE_STATE_IDLE means that the character isn't moving in XOY plane
• MOVE_STATE_WALK means that the character is moving with walking pace
• MOVE_STATE_RUN means that the character is moving with running pace

GroundState:

• GROUND_STATE_STAND means that the character is standing on the ground
• GROUND_STATE_CROUCH means that the character is crouching
• GROUND_STATE_JUMP means that the character is jumping (or falling)

JumpState:

• JUMP_STATE_UP means that the character is moving up
• JUMP_STATE_FLY means that the character is not moving in Z direction
• JUMP_STATE_DOWN means that the character is falling down

ActionState:

• ACTION_STATE_IDLE means that the character is doing nothing
• ACTION_STATE_FIRE means that the character is firing (or attacking somehow else)
• ACTION_STATE_USE means that the character is using an item

### Height

There is a set of parameters affecting height of the character (height of its collision capsule):

• height_stand is a height of a standing character
• height_crouch is a height of a crouching character
• height_change_speed is a speed of changing of height during switching from standing to crouching state or vice versa

## Actor

Actor is responsible for physical parameters of the character: movement speed, jump height, collision shape and so on. The character is approximated by a capsule in terms of collision detection.

### Configuration

Source code (XML)
``````<actor>
<min_velocity>10</min_velocity>
<max_velocity>20</max_velocity>
<min_friction>0</min_friction>
<max_friction>1</max_friction>
<damping>1</damping>
<jumping>220.0</jumping>
<turn_speed>120</turn_speed>
<turn_angle_threshold>90</turn_angle_threshold>
<move_rotation_speed>30</move_rotation_speed>
<idle_speed_threshold>0.2</idle_speed_threshold>
<ground_threshold>0.1</ground_threshold>
<acceleration>4</acceleration>
<mass>60</mass>
<turning>90</turning>
<height_stand>7</height_stand>
<height_crouch>5</height_crouch>
<height_change_speed>5</height_change_speed>
<physical>1</physical>
<min_angle>-60</min_angle>
<max_angle>89</max_angle>
</actor>``````
• min_velocity is a speed of walking
• max_velocity is a speed of running
• min_friction is a friction ratio while walking
• max_friction is a friction ratio while running
• damping is a damping ratio
• jumping is a jump ratio (affects jump height)
• turn_speed is a speed of turning after rotating camera over threshold angle
• turn_angle_threshold is a threshold angle, if angle between Angle and Yaw is less than it, the character will not turn
• move_rotation_speed is a turning speed while moving
• idle_speed_threshold is a minimal speed, after that the character is treated as moving
• ground_threshold is a distance, up to which the character is considered to be on the ground. It is measured downwards from the bottom point of the character. If intersection with the ground occurred within the set distance, character walking animation will still be played. If intersected ground is further than this distance, a character will be considered flying.
• acceleration is the character acceleration while moving
• mass is mass of the character
• turning is a turning speed in degrees per second
• height_stand is a height of the standing character (affects collision detection)
• height_crouch is a height of the crouching character
• height_change_speed is a speed of changing of height during switching from standing to crouching or vice versa
• radius is a radius of the capsule, which approximates the character for collision detection
• physical is a flag, which controls whether the actor should interact with the environment as a physical object (1) or not (0), enables or disables its rigid body
• min_angle is a minimum Pitch angle at which the camera can rotate
• max_angle is a maximum Pitch angle at which the camera can rotate

## Skin

Skin is responsible for visual appearance of the character. Animation is a sequence of frames, which describes transformations of the skin's skeleton bones.

Source code (XML)
``````<skin>
<node>demos/character/nodes/agent.node</node>
<scale>6 6 6</scale>
</skin>``````

## Locator

Locator is a binding point, which is associated with one of the bones of the Skin 's skeleton.

### Configuration

Source code (XML)
``````<locators>
<locator name="camera">Camera_bone</locator>
<locator name="weapon">agent_pistol_rhand</locator>
</locators>``````

Value inside locator tag is a target bone name.

## Attachment

Attachment is an arbitrary object (weapon, ammo, effects, etc), which is binded to a Locator.

### Configuration

Source code (XML)
``````<attachments>
<attachment name="pistol" locator="weapon">demos/character/nodes/pistol.node</attachment>
</attachments>``````

Value inside attachment tag is a node file name, locator attribute points to name of a previously defined locator.

## Camera

Camera describes a 3rd person view, following the character.

### Configuration

Source code (XML)
``````<camera locator="camera">
<anchor>0 0 7.5</anchor>
<shift>0 0 0</shift>
<fixed_distance>1</fixed_distance>
<distance>15.0</distance>
<distance_change_speed>20.0</distance_change_speed>
<type>1</type>
<collision>1</collision>
<min_angle>-28</min_angle>
<max_angle>89.9</max_angle>
<turning>90</turning>
<z_near>0.1</z_near>
<z_far>10000</z_far>
<fov>60</fov>
<min_distance>10</min_distance>
<max_distance>15</max_distance>
<zoom_step>2</zoom_step>
</camera>``````

locator attribute of the node points to name of a previously defined locator. Relative transformations of a bone associated with the locator affects the camera position (they are added to the camera transformations). Scale of the bone multiplies camera FOV.

This can be used for camera shaking while running and changing of FOV in aiming mode, for example. Since transformations of locators are controlled by animation graph, one can create different camera behaviour according to the character states.

Notice
See character scheme for better understanding of angles and so on.

Other options:

• anchor sets coordinates of a point in local space of the actor the camera is turning around
• shift is a shift of the camera position in local space of the camera
• fixed_distance is a flag, which controls whether distance from the anchor to the camera can be changed or not
• distance is a radius from the anchor to the camera
• distance_change_speed is a speed of changing distance from the anchor to the camera
• type defines the camera behaviour:
• 0 means that both Yaw and Pitch angles are fixed (they depends on the Actor position)
• 1 means that Pitch angle is fixed
• 2 means that Yaw angle is fixed
• 3 means that both Yaw and Pitch angles aren't fixed
should follow the character or move independently
• collision defines whether collision detection of the camera with other objects should be performed or not
• min_angle is a minimal pitch angle
• max_angle is a maximal pitch angle
• radius is a radius of sphere representing the camera during collision detection
• turning is a turning speed in degrees per second
• z_near is a distance to the near clipping plane
• z_far is a distance to the far clipping plane
• fov is a field of view
• min_distance is a minimal distance between the actor and the camera
• max_distance is a maximal distance between the actor and the camera

## Animation Graph

Animation Graph describes logic of the character animation in form of a graph. It must contain single root Combiner (its outgoing Animation Flow is applied to the Skin).

### Configuration

Source code (XML)
``````<animation_graph>
<combiner type="animation">
<animation start="0" end="-1">demos/character/animation/agent_walk_fwd.sanim</animation>
</combiner>
</animation_graph>``````

### Example

Here is an example of full-featured Animation Graph (see corresponding configuration file): ## Animation Flow

Animation Flow is a directed edge of an Animation Graph.

## Combiner

Combiner is a node of an Animation Graph, which can be connected with other nodes. It can contain several ingoing Animation Flows and a single outgoing. There can also be Combiner Inputs and Combiner Events associated with the Combiner.

### Common Configuration

Source code (XML)
``````<combiner type="...">
<inputs>
<input name="speed" type="function" scale="3" shift="0">Character::getSpeed</input>
</inputs>
<events>
<event on="activate" callback="CombinerAnimation::setPhase">
<arg type="function">Character::getStepPhase</arg>
</event>
<event on="update" callback="Character::setStepPhase">
<arg type="function">CombinerAnimation::getPhase</arg>
</event>
</events>

... custom data ...

</combiner>``````

type attribute sets type of the Combiner, it can have one of the following values:

## Combiner Input

Combiner Input is an input for parameter, which contols logic of the Combiner. So Combiner's internal logic can be controlled by outside environment.

There are two types of Inputs: const (constant value) and function (a value returned from a function call). Each Input has its own name.

### Const Input

A constant value.

Source code (XML)
``<input name="speed" type="const">5</input>``

### Function Input

A sequence of values returned by a function.

Source code (XML)
``<input name="pos_x" type="function" scale="0.5556" shift="50" min="0" max="100" smooth="400">Character::getYaw</input>``

You can tweak the value by setting scale, shift, min, max parameters, result will be calculated according to the following formula:

Source code (UnigineScript)
``result = clamp(value * scale + shift,min_value,max_value);``
Some values vary by leaps and bounds, this can be undesirable for animation playback. To prevent this spikes there is a smooth parameter, which works this way (if smooth value is greater than 0):
Source code (UnigineScript)
``delta = sign(old_delta) * min(abs(old_delta),dt * smooth)``
Here:
• old_delta is a difference between previous and current values
• delta is a difference between current and next values
• dt is a time period passed since last update of the parameter
In other words changes of the parameter value will be limited by " smooth per second".

## Combiner Event

It is possible to assign a function call to an event occured in a Combiner. Therefore it's possible to create a logic depending on animation (animation feedback).

For example one needs to lock controls while the character is flying in the air. Let's assume that we have a Combiner in Animation Graph, which is active while the character has no contact with surface. The following is one of the CombinerSwitch 's flows, which detects whether the character is staying or flying:

Source code (XML)
``````<!-- jump -->
<case value="2" blend_speed="5">
<combiner type="...">
<events>
<event on="activate" callback="Character::setControlEnabled">
<arg type="const">0</arg>
</event>
<event on="deactivate" callback="Character::setControlEnabled">
<arg type="const">1</arg>
</event>
</events>

... some combiner logic ...

</combiner>
</case>``````

Parameters:

• on is an event type. There is a set of standart events (however, it can be extended, depending on Combiner's type):
• activate means that the Combiner is switched into active state
• deactivate means that the Combiner is switched off
• update occurs every frame
• callback is a target function name to be called
• arg is a parameter passed to the target function (there can be multiple "arg"'s, they are passed in the order of occurrence in the Event definition); syntax is similar to Combiner Input (so you can use both constant and function-produced values)

## Built-In Combiners

### CombinerAnimation

#### Description

This Combiner returns current frame of an animation loaded from a file. If the Combiner is active, it's playing animation with given speed.

#### Example

Source code (XML)
``````<combiner type="animation">
<inputs>
<input name="speed" type="const">1.0</input>
</inputs>
</combiner>``````

#### Parameters

• animation is a file name
• start is a starting frame number
• end is an ending frame number (-1 means the last)

#### Inputs

The Combiner has only one Input, speed (frames per second, default value is 1.0, negative values are also acceptable for reverse playback).

### CombinerBlend

#### Description

This Combiner mix two Animation Flows according to blend coefficient (if the coefficient is equal to 0.0, so outgoing Animation Flow will be the same as the first ingoing Animation Flow, if it's equal to 1.0, then outgoing Animation Flow will be the second ingoing one)

The Combiner works according to these formulas:

Source code (UnigineScript)
``````pos = lerp(src_pos,dst_pos,weight);
rot = slerp(src_rot,dst_rot,weight);
scale = lerp(src_scale,dst_scale,weight);``````

#### Example

Source code (XML)
``````<combiner type="blend">
<inputs>
<input name="weight" type="const">0.5</input>
</inputs>
<flows>
<flow>
<combiner type="animation">
<animation start="0" end="-1">demos/character/animation/agent_walk_fwd.sanim</animation>
</combiner>
</flow>
<flow>
<combiner type="animation">
</combiner>
</flow>
</flows>
</combiner>``````

#### Inputs

weight sets blending proportion (default value is 0.5, acceptable values are from 0 to 1).

#### Description

This Combiner sum up two Animation Flows.

The Combiner works according to these formulas:

Source code (UnigineScript)
``````pos = src_pos + dst_pos * weight;
rot = slerp(src_rot,src_rot * dst_rot,weight);
scale = slerp(src_scale,src_scale * dst_scale,weight);``````

#### Example

Source code (XML)
``````<combiner type="add">
<inputs>
<input name="weight" type="const">0.5</input>
</inputs>
<flows>
<flow>
<combiner type="animation">
<animation start="0" end="-1">demos/character/animation/agent_walk_fwd.sanim</animation>
</combiner>
</flow>
<flow>
<combiner type="animation">
</combiner>
</flow>
</flows>
</combiner>``````

#### Inputs

weight can be from 0.0 (outgoing Animation Flow is equal to the first ingoing one) to 1.0 (outgoing Animation Flow is a sum of ingoing ones), default value is 1.0.

### CombinerSub

#### Description

This Combiner substract the second Animation Flow from the first one.

The Combiner works according to this formula:

Source code (UnigineScript)
``res = Add(src,Invert(dst));``

#### Example

Source code (XML)
``````<combiner type="sub">
<inputs>
<input name="weight" type="const">0.5</input>
</inputs>
<flows>
<flow>
<combiner type="animation">
<animation start="0" end="-1">demos/character/animation/agent_walk_fwd.sanim</animation>
</combiner>
</flow>
<flow>
<combiner type="animation">
</combiner>
</flow>
</flows>
</combiner>``````

#### Inputs

weight can be from 0.0 (outgoing Animation Flow is equal to the first ingoing one) to 1.0 (outgoing Animation Flow is equal to the first ingoing one minus the second one), default value is 1.0.

### CombinerSubstitute

#### Description

Substitutes the first ingoing Animation Flow with transformations of bones from the second one, to be used for combination of animations. It's especially useful if one needs to override animation for some specific bones only.

#### Example

Source code (XML)
``````<combiner type="substitute">
<flows>
<flow>
<combiner type="animation">
<animation start="0" end="-1">demos/character/animation/agent_walk_fwd.sanim</animation>
</combiner>
</flow>
<flow>
<combiner type="animation">
</combiner>
</flow>
</flows>
</combiner>``````

### CombinerInvert

#### Description

Inverts an Animation Flow.

The Combiner works according to these formulas:

Source code (UnigineScript)
``````pos = -src_pos;
rot = inverse(src_rot)(-src_rot);
scale = 1.0/src_scale;``````

#### Example

Source code (XML)
``````<combiner type="invert">
<flows>
<flow>
<combiner type="animation">
</combiner>
</flow>
</flows>
</combiner>``````

### CombinerIdentity

#### Description

Sends ingoing Animation Flow as outgoing one without modifications.

#### Example

Source code (XML)
``````<combiner type="identity">
<flows>
<flow>
<combiner type="animation">
</combiner>
</flow>
</flows>
</combiner>``````

### CombinerNull

#### Description

Generates empty outgoing Animation Flow, to be used for debugging purposes only.

#### Example

Source code (XML)
``<combiner type="null"/>``

### CombinerSwitch

#### Description

Chooses one of the Animation Flows according to an Input parameter.

Input parameters are casted to int. If no case fits value of the input parameter, default one is used. Blending into the new state is performed with given speed.

#### Example

Source code (XML)
``````<!-- stand idle -->
<combiner type="switch">

<inputs>
<input name="case" type="function" scale="1" shift="0">Character::getRotationSpeedSign</input>
</inputs>

<switch>

<!-- stand -->
<case value="0" blend_speed="3">
<combiner type="animation">
<inputs>
<input name="speed" type="const">10</input>
</inputs>
</combiner>
</case>

<!-- turninig left & right -->
<default blend_speed="5">
<combiner type="animation">
<inputs>
<input name="speed" type="function" scale="-0.455" shift="0">Character::getRotationSpeed</input>
</inputs>
<animation start="0" end="-1">demos/character/animation/agent_idle_turn_lft_90.sanim</animation>
</combiner>
</default>

</switch>
</combiner>``````

#### Parameters

• value is a condition of transition to a state (it's ignored for default case)
• blend_speed is a blending duration in 1/second

#### Inputs

case defines the input parameter, which is checked for matching with cases of the switch statement.

#### Events

Root combiners of each case have the following events:

• blend_in_start occurs when blending into a state is started
• blend_in_end occurs when blending into a state is completed
• blend_out_start occurs when blending from a state is started
• blend_out_end occurs when blending from a state is completed
These events are generated only if state of the CombinerSwitch is changed, they don't occur on activation of the combiner (use standart activate and deactivate events to handle this).

### CombinerLine

#### Description

This Combiner allows creation of a complex animations, which depends on a parameter.

For example, one needs to keep orientation of the character's torso while playing animations of running in different directions. In this case there should be animations of running forward, backward and to the left, to the right. Plus one has to pass angle between torso orientation and movement direction as an Input parameter. See the following example to get an idea of such CombinerLine usage.

#### Example

Source code (XML)
``````<!-- run -->
<combiner type="line">

<inputs>
<input name="pos" type="function">Character::getRelativeMoveAngle</input>
</inputs>

<line min="-180" max="90">

<!-- move backward -->
<key pos="-180">
<combiner type="animation">
<animation start="0" end="-1">run_backward.sanim</animation>
</combiner>
</key>

<!-- strafe left -->
<key pos="90">
<combiner type="animation">
<animation start="0" end="-1">run_left.sanim</animation>
</combiner>
</key>

<!-- move forward -->
<key pos="0">
<combiner type="animation">
<animation start="0" end="-1">run_forward.sanim</animation>
</combiner>
</key>

<!-- strafe right -->
<key pos="-90">
<combiner type="animation">
<animation start="0" end="-1">run_right.sanim</animation>
</combiner>
</key>

</line>
</combiner>``````

#### Parameters

line node has the following parameters:

• min is a minimal acceptable value of the input parameter
• max is a maximal acceptable value of the input parameter

Each key node has pos parameter, which sets a position of the key on the line.

If min or max values of the line aren't defined, they will be calculated automatically according to the available keys. Even if min and max values are set, pos values of a key can be out of the range (thus you can use only required range of values).

#### Inputs

pos is a current position on the line.

### CombinerGrid

#### Description

This Combiner allows creation of a complex animations, which depends on two parameters. Keys are distributed equidistantly on a 2D grid.

For example, it can be used for complex animation of aiming (it requires 9 poses of aiming).

#### Example

Source code (XML)
``````<combiner type="grid">

<inputs>
<input name="pos_x" type="function" shift="90" min="0" max="180" smooth="400">Character::getYaw</input>
<input name="pos_y" type="function" shift="90" min="0" max="180" smooth="400">Character::getPitch</input>
</inputs>

<grid num_keys_x="3" num_keys_y="3" max_x="180" max_y="180">
<key pos_x="0" pos_y="0">
<combiner type="animation">
<animation start="0" end="-1">demos/character/animation/agent_idle_anim_rt_up_torso.sanim</animation>
</combiner>
</key>
<key pos_x="1" pos_y="0">
<combiner type="animation">
<animation start="0" end="-1">demos/character/animation/agent_idle_anim_fwd_up_torso.sanim</animation>
</combiner>
</key>
<key pos_x="2" pos_y="0">
<combiner type="animation">
<animation start="0" end="-1">demos/character/animation/agent_idle_anim_lt_up_torso.sanim</animation>
</combiner>
</key>
<key pos_x="0" pos_y="1">
<combiner type="animation">
<animation start="0" end="-1">demos/character/animation/agent_idle_anim_rt_torso.sanim</animation>
</combiner>
</key>
<key pos_x="1" pos_y="1">
<combiner type="animation">
<animation start="0" end="-1">demos/character/animation/agent_idle_anim_fwd_torso.sanim</animation>
</combiner>
</key>
<key pos_x="2" pos_y="1">
<combiner type="animation">
<animation start="0" end="-1">demos/character/animation/agent_idle_anim_lt_torso.sanim</animation>
</combiner>
</key>
<key pos_x="0" pos_y="2">
<combiner type="animation">
<animation start="0" end="-1">demos/character/animation/agent_idle_anim_rt_down_torso.sanim</animation>
</combiner>
</key>
<key pos_x="1" pos_y="2">
<combiner type="animation">
<animation start="0" end="-1">demos/character/animation/agent_idle_anim_fwd_dwn_torso.sanim</animation>
</combiner>
</key>
<key pos_x="2" pos_y="2">
<combiner type="animation">
<animation start="0" end="-1">demos/character/animation/agent_idle_anim_lt_down_torso.sanim</animation>
</combiner>
</key>
</grid>
</combiner>``````

#### Parameters

grid parameters:

• num_keys_x is a number of the grid elements in X direction
• num_keys_y is a number of the grid elements in Y direction
• max_x is a position of the last key of the grid in X direction
• max_y is a position of the last key of the grid in Y direction
key parameters:
• pos_x is a position of a key in X direction
• pos_y is a position of a key in Y direction

#### Inputs

• pos_x is a current position on the grid in X direction (default value is 0)
• pos_y is a current position on the grid in Y direction (default value is 0)

## Usage

### Extending Base Character

To create a character with extended logic you have to inherit your own class from Unigine::Character and extend its update() method. Plus you can add some code to save and load some extra data.

Source code (UnigineScript)
``````#include <scripts/character/character.h>

namespace Custom {

class CustomCharacter : Unigine::Character {
// constructor
CustomCharacter(string name) {
Unigine::Character::init(name);
}

// update character
void update(float ifps) {
Unigine::Character::update(ifps);
custom_character_logic();
}

// save character
void save(Xml xml) {
Unigine::Character::save(xml);
custom_character_save(xml);
}

Unigine::Character::save(xml);
}
};

}``````

### Creating a Character

You need to call initCharacter() function to initialize the character system.

Source code (UnigineScript)
``````// world initialization function
int init() {
Unigine::initCharacter();
// now you create your character and place it somewhere in the world:
character = new Custom::CustomCharacter("demos/character/agent.character");
character.setPosition(vec3(23.7,-48.5,0.0));
}``````

### Updating the Character

You have to call update() function every frame to get the character working.

Source code (UnigineScript)
``````// world update function
int update() {
float ifps = engine.game.getIFps();
character.update(ifps);
}``````

### Using Parameters from the Configuration File

You can use parameters of the current character or Combiner because calling functions from namespace of the class takes active context into the account.

Source code (UnigineScript)
``````class Foo {

int getBarValue() {
return call("Bar::getValue");
}

};

class Bar {

Foo foo;

int value;

Bar(int value_) {
value = value_;
foo = new Foo();
}

int getValue() {
return value;
}

Foo getFoo() {
return foo;
}

int getFooBarValue() {
return foo.getBarValue();
}

};

Bar bar10 = new Bar(10);
Bar bar20 = new Bar(20);
int value;

// the following fragment doesn't work:
Foo foo = bar10.getFoo();
engine.console.print("value = %d\n",foo.getBarValue());

// this one works:
engine.console.print("value = %d\n",bar10.getFooBarValue());
engine.console.print("value = %d\n",bar20.getFooBarValue());``````

Here is an example of access to a parameter of the base character:

Source code (XML)
``<input name="speed" type="function" scale="3" shift="0">Character::getSpeed</input>``

Source code (XML)
``<input name="speed" type="function" scale="3" shift="0">Custom::CustomCharacter::getMyCustomParameter</input>``

### Character Parameters API

• int Unigine::Character::isControlEnabled() indicates whether controls is locked or not
• int Unigine::Character::isTurnEnabled() indicates whether angle between Angle and Yaw is greater than turn_angle_threshold
• float Unigine::Character::getStepPhase() returns phase of a step (to be used for sync of running and walking phases, etc)
• float Unigine::Character::getSpeed() returns speed of the character in XOY plane
• float Unigine::Character::getSpeedZ() returns vertical speed of the character
• float Unigine::Character::getYaw() returns azimuth angle of aiming relatively to Angle
• float Unigine::Character::getPitch() returns zenith angle of aiming
• float Unigine::Character::getAngle() returns Angle value
• float Unigine::Character::getRotationSpeed() returns changing speed of Angle 's value
• float Unigine::Character::getRotationSpeedAbs() returns modulo of changing speed of Angle 's value
• float Unigine::Character::getRotationSpeedSign() returns sign of changing speed of Angle 's value
• int Unigine::Character::getJumpState() returns JumpState
• int Unigine::Character::getGroundState() returns GroundState
• int Unigine::Character::getMoveState() returns MoveState
• int Unigine::Character::getActionState() returns ActionState

### Character Events API

Here is the list of character functions, which can be used as events:

• void Unigine::Character::setControlEnabled(int state) is used to enable/disable controls
• void Unigine::Character::setTurnEnabled(int state) is used to enable/disable in-place turns
• void Unigine::Character::setStepPhase(float step_phase_) sets phase of the step

There are also Combiner's functions, which can be used as events:

• float Unigine::CombinerAnimaiton::getPhase() gets phase of the animation (return values are from 0.0 to 1.0, where 0.0 means the first frame and 1.0 is for the last one)
• void Unigine::CombinerAnimaiton::setPhase(float phase) sets phase of the animation

### Phase Sync

You can sync phases of walking and running by the following method:

Source code (XML)
``````<!-- stand run -->
<case value="2" blend_speed="5">
<combiner type="animation">
<inputs>
<input name="speed" type="function" scale="1.7" shift="0">Character::getSpeed</input>
</inputs>
<events>
<!-- get a current step phase to the current combiner when the combiner becomes active -->
<event on="activate" callback="CombinerAnimation::setPhase">
<arg type="function">Character::getStepPhase</arg>
</event>
<!-- set a current step phase to the current character when the combiner is updated -->
<event on="update" callback="Character::setStepPhase">
<arg type="function">CombinerAnimation::getPhase</arg>
</event>
</events>
<animation start="0" end="-1" speed="10">demos/character/animation/agent_run_fwd.sanim</animation>
</combiner>
</case>``````
Last update: 2017-10-20