Emotion scripting API

Reference for the emotion scripting surface — ConvaiEmotionController, EmotionReading, override and lock methods, C# events, and IEmotionStateSource.

The Emotion system exposes two distinct paths for reacting to and controlling emotional state at runtime. The Inspector path uses ConvaiCharacterEventRelay — a component that surfaces emotion change callbacks as standard Unity Events, requiring no code. The scripting path uses ConvaiEmotionController directly, exposing a full C# API for reading live state, injecting overrides, and locking expressions. Both paths can be used simultaneously.

Inspector path — ConvaiCharacterEventRelay

ConvaiCharacterEventRelay is a MonoBehaviour that bridges character callbacks to Unity Events, allowing designers to wire emotion reactions entirely in the Inspector without writing any code.

Add Component: Convai → Events → Convai Character Event Relay

Place it on any GameObject in the scene. It automatically finds the ConvaiCharacter on the same GameObject, or you can assign a character from a different GameObject via the Character field.

Inspector fields

Field
Default
Description

Character

(none)

Optional explicit reference to a ConvaiCharacter. Leave empty to use auto-resolve.

Auto Resolve Character

true

When enabled, the relay finds a ConvaiCharacter on the same GameObject automatically.

OnEmotionChanged event

The relay exposes an On Emotion Changed Unity Event that fires whenever the character's emotion signal changes. The event delivers a CharacterEmotionRelayData payload:

Property
Type
Description

CharacterId

string

Unique identifier of the character.

CharacterName

string

Display name of the character (falls back to the GameObject name).

Emotion

string

The raw server label (e.g. "happy").

Intensity

int

Integer scale 1–3 as sent by the backend.

Example wiring: Add a ConvaiCharacterEventRelay to your NPC's GameObject. In the On Emotion Changed list, click +, drag a UI Text component into the object field, and select Text.text — the label will update automatically on every emotion change.

ConvaiCharacterEventRelay fires on the raw server label before taxonomy resolution or smoothing. Use it for UI display, audio cues, or simple branching logic. For smoothed, post-resolution state with scores and hold time, use ConvaiEmotionController.Current from script instead.

Accessing the controller from script

The ConvaiEmotionController component can be retrieved by its concrete type or through the IEmotionStateSource interface. Use the interface when you want to decouple your code from the specific component implementation:

Reading current emotion state

ConvaiEmotionController.Current returns an EmotionReading — an immutable snapshot rebuilt every frame from the accumulator's output. Poll it in Update or react to it on any event.

EmotionReading properties and methods

Member
Type
Description

DominantLabel

string

Canonical label of the highest-scoring emotion (e.g. "joy", "anger").

DominantScore

float

Normalised score [0–1] for the dominant emotion after smoothing and burst.

AllScores

IReadOnlyDictionary<string, float>

Full score table keyed by canonical label. Every emotion in the taxonomy has an entry. Emotions with no contribution this frame have a score of 0.

MouthInfluence

float

[0–1] hint consumed by the LipSync compositor to blend mouth shapes during non-speaking frames.

DominantHoldSeconds

float

Wall-clock seconds the current dominant label has been held continuously.

IsNeutral

bool

true when the dominant label is "neutral" or when DominantScore ≤ 0.

NeutralLabel

const string

The string constant "neutral".

GetScore(string canonicalLabel)

float

Returns the smoothed score for the given canonical label, or 0 when absent.

CopyScoresTo(IDictionary<string, float> destination)

void

Copies the full score table into a caller-owned dictionary. Clears the destination before copying.

Authoring-time lock

The controller has three serialised fields that fix the expression to a specific emotion directly from the Inspector — useful during authoring and debugging, or to preview blendshape slot results in the Scene view without entering Play Mode.

Field
Type
Default
Description

lockEmotion

bool

false

When enabled, all incoming server emotion events are ignored and the character holds the locked emotion.

lockedEmotionLabel

string

"neutral"

Canonical taxonomy label to hold while lockEmotion is active.

lockedIntensity

float

1.0

Intensity [0–1] of the locked emotion.

ConvaiEmotionController inherits [ExecuteAlways] from its base class. Setting lockEmotion = true in the Inspector updates blendshapes in the Scene view immediately, without entering Play Mode. This makes it a practical tool for verifying that slot mappings produce the correct visual result on your character mesh.

SetEmotionOverride and ClearEmotionOverride

SetEmotionOverride injects an additional score into the accumulator on top of whatever the server is sending. The override is still subject to smoothing — it blends in at lerpSpeed, not instantly. Use this when your application logic needs to amplify or steer emotion in response to in-scene events.

ClearEmotionOverride removes the override and returns the accumulator to server-driven state. The transition back is smoothed.

LockEmotion and UnlockEmotion

LockEmotion bypasses the accumulator entirely, snapping the character to a specific expression and holding it there regardless of what the server sends. Use this when you need a guaranteed, stable expression during scripted sequences.

UnlockEmotion releases the lock. The accumulator resumes from neutral and begins responding to server events again.

API signatures:

Subscribing to emotion change events

To react to each new emotion the backend sends — for logging, analytics, or adaptive scenario logic — subscribe to OnCharacterEmotionChanged on ConvaiManager.Events. This is a standard C# event; subscribe in OnEnable and unsubscribe in OnDisable.

CharacterEmotionChanged properties

Property
Type
Description

CharacterId

string

Unique identifier of the character whose emotion changed.

Emotion

string

The raw server label (e.g. "happy", not the canonical "joy").

Intensity

int

Integer scale 1–3 as sent by the backend (clamped).

NormalizedIntensity

float

(Intensity - 1) / 2f — maps the 1–3 range to [0, 1].

IsNeutral

bool

true if the emotion string is "neutral".

IsHighIntensity

bool

true if Intensity >= 3.

IsLowIntensity

bool

true if Intensity <= 1.

Timestamp

DateTime

UTC timestamp of when the event was created.

IEmotionStateSource interface

Code that only needs to read emotion state — without controlling overrides or locks — should depend on IEmotionStateSource rather than the concrete ConvaiEmotionController. This keeps the dependency minimal and makes the consuming class easier to test.

Next steps

For complete worked examples that combine profile configuration with these API calls, see Emotion examples. If something is not behaving as expected at runtime, see Troubleshoot emotion.

Emotion examplesTroubleshoot emotion

Last updated

Was this helpful?