Skip to content

Characters

This section is about manipulating actors representing characters participating in the dialogue.

Identifying Characters

In order the manipulate characters, we first have to be able to identify them in the dialogue script. Any actor which wishes to be identified as a character in the dialogue must:

  1. Be a Participant in the dialogue
  2. Implement the ISudsProCharacter interface.

Item 1 is covered easily if you're using Suds Pro Runner to run your dialogue; the main player character is automatically added to the participants, and so are any actors you add to the NPCs list:

RunnerNPCs

In your characters You need to implement "Get Dialogue Character Identifier" from ISudsProCharacter. Ideally use the same value as their usual SpeakerID in dialogues, although that's not required. Then whenever you refer to this identifier in character related events, that actor will be located as the target of the command.

Moving Characters

You often want to move characters in a dialogue into known positions so that your dialogue can work nicely; that they're not clipping into geometry when emoting, and the camera shots look good.

Marks

In movies, there's a concept of actors needing to "hit their marks", so that they're in the right spot to frame a dialogue camera shot nicely.

SUDS Pro comes with a class called "BP_DialogueCharacterMark", which provides 2 things:

  1. A "mark" position/rotation
  2. A visual placeholder

The visual placeholder is useful when framing shots. You can set a representative skeleton and idle animation in its properties:

The placeholder will not be displayed at game time.

Moving characters to a Mark

You can teleport a character to a mark like this:

[event CharacterMove `Identifier`, `MarkName`]

`Identifier` is the identifier of the character, as discussed above.

`MarkName` needs to be discoverable; the easiest way is when you're already using the Suds Pro Runner to organise your dialogue, in which case you can just link the level instance of the mark with a name:

Marks list

Under the hood, any Participant which implements ISudsProMarkProvider can provide a mapping from a mark name to a real mark instance. The mark itself can also be any object, even just an empty actor. But we recommend using the utility classes provided with SUDS Pro wherever you can for simplicity.

Fading around character moves

To hide the fact that you're moving a character, you might want to use Fades.

For example:

[event FadeOut]
[event CharacterMove `Player`, `PlayerMark`]
[event FadeIn]

You might think that you need a WaitFade (see Waiting) event in between FadeOut and CharacterMove, because things generally run all at the same time. However, SUDS Pro is smart enough that if it sees a FadeOut is happening when a CharacterMove comes up, it automatically waits for the fade to complete before continuing.

If you'd rather it didn't do this, you can disable it:

[set CharacterMoveWhileFading true]

Animating Characters

Another common requirement is making a character animate, or "emote", during dialogue.

Here's how you'd tell a character called Manny to play an animation called Wave:

[event CharacterAnim `Manny`, `Wave`]

The character Manny is identified as described above. the animation Wave is resolved to an animation asset (sequence or a montage) in one of two ways:

  1. Your character class can implement the ISudsProCharacter function "Get Dialogue Animation", and return an animation for the given name
  2. If step 1 doesn't resolve to a valid animation, any other Participant in the dialogue can implement the ISudsProAnimationProvider function "Get Dialogue Character Animation", and return an animation for a given character name & animation name.

Here's an example of the first approach:

Dialogue Animation

This means you can write your dialogue scripts with general emote names without worrying about specific animation assets, and resolve them later to the real animations per character.

Targeting specific skeletal mesh components

The default behaviour for animations is finding the first Skeletal Mesh Component on a character. If you have multiple Skeletal Mesh Components on a character (e.g. one for the head, one for the body like Metahuman), the you will need to have separate animations for each, e.g. "Face_Smile" or "Body_Dance" (prefixes are good practice).

You will then need to implement the ISudsProCharacter function "Get Dialogue Skeleton" to return the correct skeletal mesh component for a given animation name (this is where the prefix is useful).

Dialogue Animation

In the case of multiple skeletal mesh components, you can actually play more than one animation concurrently, one per skeletal mesh component (because they are montages). For example:

[event CharacterAnim `Manny`, `Body_Wave`]
[event CharacterAnim `Manny`, `Face_Smile`]

Looping Animation

If your animation refers to an Animation Sequence, the default is to play it once. If you want it to be played more times, you can provide a number of loops as the 3rd argument:

# Loops the Wave animation 3 times
[event CharacterAnim `Manny`, `Wave`, 3]

Other Animation Options

When using an animation sequence you can also specify the blend times and play rate. By default the blend times are 0.25 seconds and play rate is 1 if not specified.

Note: when using Montages you don't need to specify any of this because Montages include their own blend & play rate settings.

# Plays the wave once, but blends it in for 0.5s, blends out for 0.25s and plays it at 1.5x speed
[event CharacterAnim `Manny`, `Wave`, 1, 0.5, 0.25, 1.5]

Stopping Animation

If you want to stop running animation early, use the CharacterAnimStop event:

[event CharacterAnimStop `Manny`]

Note: without any other arguments this stops the animation on the default skeleton. If you have multiple skeletal mesh components as descrived above, you may need the second optional argument:

[event CharacterAnimStop `Manny`, `Face_Smile`]

This stops animation on the skeleton which would be affected by the animation Face_Smile. If you use prefixes in your implementation of "Get Dialogue Skeleton", you can in fact use any animation name which your code will recognise (so you could just use Face_ if that's your prefix), since we're not explicitly stopping the animation, just all animation on that skeleton.

Animation Sequences & Slots

When playing animation sequences, SUDS Pro asks the character to run it via an Animation Slot.

Therefore in order for animation sequences to work, the animation blueprint for your characters must have an Animation Slot configured, ideally called "DefaultSlot".

You can just tack it on the end of your Anim Graph just before the output, or perhaps just before Control Rig if you're using it; here's an example:

Anim Graph

Being called "DefaultSlot" means you don't have to specify the slot name in the CharacterAnim events. For any other slot name, you have to specify it:

[event CharacterAnim `Manny`, `Wave`, 1, `CustomSlotName`]

Animation Montages

Animation names can also refer to Animation Montages rather than sequences. Montages already know what slot(s) they target with their animation, and can include their own looping sections, so the slot name, loops, blend in/out times and play rate parameters are redundant.

Waiting for character animations

Like most things, character animation runs in parallel and the script usually continues while it's playing. You can pause the continuation of the dialogue until a character's animation is complete like this:

[event WaitCharacter `Manny`]

If you run multiple animations at once because you have multiple skeletal mesh components, this wait will only complete when all the animations are complete.

Character Notifications

What if you want to send a notification from the dialogue to a specific character? Here's how you can do that:

[event CharacterNotify `Identifier`, `NotificationName`, Args...]

The character identified will have its "On Dialogue Notify" function called, which is one of the functions on the ISudsProCharacter interface.

The arguments after NotificationName will all be passed to the function, and they can of course be dialogue variables or expressions.

Because arguments are a variable type (FSUDSValue), you should use the provided helper functions to extract the actual values:

SUDS Value Helpers

"On Dialogue Notify" has a boolean return value. If you return false, the dialogue script will carry on running. If you return true, the the dialogue will pause and not execute any more lines until you call USudsProSubsystem::CharacterNotifyComplete.

Updating Character Properties

Sometimes you might want the dialogue to modify properties on characters directly. For example, you might want to trigger state changes in the animation blueprint, instead of fire-and-forget animations as with CharacterAnim.

Note that you can do this sort of thing by monitoring dialogue variable state. Any participant can be notified of variable changes, so that's another way to do it. But, being able to set character properties directly is a bit simpler and has the ability to target specific characters.

[event CharacterPropSet `Identifier`, `PropertyName`, Value]

`Identifier` is the identifier of the character, as discussed above.

`PropertyName` must match the name of a publicly settable property on the character so identified.

Value can be a literal value, a variable, or an expression. It must match or be compatible with the type of the property on the character.

SUDS Pro currently only supports top-level properties on characters, of type FString, FText, int, float, bool and FName.

There isn't a corresponding CharacterPropGet. Use USUDSDialogue::SetVariable to get state into the dialogue.