Skip to content

Writing Your First Script

Scripts and Dialogues

SUDS Pro has two primary concepts:

  • Script: This is a sequence of dialogue lines, including all the possible routes through that dialogue. Think of it like a movie script.
  • Dialogue: This is a runtime instance of a Script. The Dialogue essentially steps through the script based on choices the player makes.

For this section, we're concerned only with writing the Script. We'll cover how to test your script, and how to run it in-game later.

Source Scripts and Unreal Assets

You write the script as a text file, with the extension .sud. We'll call this the SUDS Script Source File.

When you save a file of type .sud inside your Unreal Engine content folder, it'll be imported into a SUDS Script Asset. This is the same as if you put a PNG file in your content directory and imported it into a Texture Asset.

Import Process

In fact you get both a Script Asset and a String Table, which helps with localisation.

Note: From UE 5.3 you can no longer see the String Table asset in the content browser. They are still there, but UE 5.3 changed something that made it hide secondary assets stored in a common package. Luckily you don't need to see the String Table assets, just the scripts - just know that they're there. The Localisation Dashboard will still see them.

You'll always be writing your dialogue as .sud files in a text editor, but at runtime you'll be using the SUDS Script Assets. They're small and efficient because all the work to interpret them has already been done in the importer.

The VSCode extension means "SUDS" is a recognised language and will be automatically used whenever you save a file with the .sud extension.

Writing A Script

Scripts Are Line Based

To keep things simple, SUDS scripts are line-based. Each line is considered as a whole and does one thing. You can't split something over 2 lines, or combine multiple statements into a single line.

Lines are trimmed at the start & end

You don't have to worry about whitespace at the start/end of your lines, it will be removed. However indenting can matter when it comes to branching due to player choices, which we'll cover later.

Speaker lines

The basic building block of a script is the speaker line. This is some kind of speaker saying a line of dialogue, for example:

Vagabond: Well met, fellow traveller!

In this case the speaker is "Vagabond", and the text is "Well met, fellow traveller!". That's it, you've created your first script 😄. If you imported this single line source script into Unreal and ran a dialogue based on it, it would issue that single line before ending.

When there are multiple speaker lines, each line is self-contained, and the dialogue must be stepped forward for the next line to appear. Usually this would be a "Continue" prompt for the player:

Vagabond: Well met, fellow traveller!
Vagabond: Nice day, isn't it?

In this case, only the first line would be displayed to the player, until the dialogue was continued (e.g. by pressing a button), when the next line would be displayed.

Multi-line text

Speaker lines can have carriage returns in them. All plain text lines following a speaker line will append that text to the speaker line, with the carriage returns preserved. Only encountering another type of line will terminate the string. For example:

Vagabond: Well met, fellow traveller!
          How are you today?
Vagabond: What, cat got your tongue?

This represents 2 speaker lines issued one after the other, the first of which has a carriage return in it. Notice how I've aligned the text - I didn't need to do that, but I can if I want to make things neater because whitespace is trimmed.

Speaker IDs vs Speaker Names

Technically the prefix "Vagabond" in the previous example is the speaker ID, not the display name, but if you don't specify otherwise, that speaker ID is used as the display name as well.

One limitation is that Speaker ID's can't have whitespace in them. For this and other reasons (brevity, localisation) you might want to use a short internal term for the speaker ID, and explicitly define Speaker Display Names for showing the player. But we won't do that right now.

Choice lines

Multiple speaker lines following each other simply require the player to step through them in sequence, but when you want to branch the dialogue based on a decision by the player, you add choice lines.

Vagabond: Well met, fellow traveller!
  * Er, hi?
    Vagabond: Verily, 'tis wondrous to see such a fine fellow on the road this morn!
  * (Keep quiet)
    Vagabond: What, cat got your tongue?
  * Jog on, mate
    Vagabond: Well, really! Good day then sir!
Narrator: (The Vagabond leaves)

Choice lines begin with an asterisk (*), much like a bullet point list in Markdown. Speaker lines look ahead to see if there are choices ahead (before the next speaker line) and if so add choices to the next step. Technically you can have a single choice line, which means there's no branch in the dialogue, but adds text to the only forward choice.

Choice lines don't have to be indented from the text but it's neater to do so. Everything following the asterisk is the text to be displayed to the player as the choice option.

When a player picks one of those option, the lines underneath the choice line are run. These lines must be indented to at least one character inward of the asterisk. You can embed as many lines as you want in there, and of course other choices. You can nest as deeply as you want, although it gets a bit unwieldy eventually and you'll probably want to use a goto (see below).

When you run out of lines in a nested section, dialogue "falls through" to the next less indented line on the same narrative path. So in this case, all 3 choices will show one unique speaker line, then fall through to the "Narrator" line at the end.

Comments

You can include comments in your script by starting the line with a hash/pound (#) character:

# This is a Comment
NPC: Did you say something?

Goto lines

Sometimes you just want to jump the conversation somewhere else. Goto lines are one of the many instruction lines which start and end with square brackets ([]):

[goto <Label>]

Where <Label> is the name of a label you've defined somewhere else in the script, or end (which terminates the dialogue).

Labels are defined on their own lines like this:

:SomeLabel

Here's an example of it in action:

Vagabond: Well met, fellow traveller!
  * Er, hi?
    Vagabond: Verily, 'tis wondrous to see such a fine fellow on the road this morn!
    [goto FriendlyChat]
  * Jog on, mate
    Vagabond: Well, really! Good day then sir!
    [goto end]

:FriendlyChat
Vagabond: Mayhaps we could travel together a while, and share a tale or two?

You can actually goto any line, not just a speaker line. For example if you goto a choice line after a speaker line, it will append the choices after the goto to that speaker line as if the choices were directly under it. This is very useful for making looping dialogue.

There's Much More!

There are plenty of other features which we don't have time for in this simple version, take a look at the script reference for details.

For now, we're going to crack on just with this simple set and get it up and running in Unreal.

Importing the Dialogue

Let's put all this together into a simple script:

Vagabond: Well met, fellow traveller!
  * Er, hi?
    Vagabond: Verily, 'tis wondrous to see such a fine fellow on the road this morn!
    Vagabond: Mayhaps we could travel together a while, and share a tale or two?
    Player: Er...
    :chatchoices
      * Ask Name
        Player: I think I should know your name first.
        Vagabond: Oh, I think that would take some of the mystery out of it, don't you?
        Vagabond: We can share our stories on the road anyhow, no point lollygagging here, hmm?
        [goto chatchoices]
      * Accept
        Player: Um, sure?
        Vagabond: Wonderful, I promise you won't regret it...
        [goto end]
      * Reject
        Player: Sorry, I prefer to travel alone.
        Vagabond: Hmpf, that's a shame. Farewell to you then, LONE traveller!
        [goto end]
  * Jog on, mate
    Vagabond: Well, really! Good day then sir! *flounce*
    [goto end]

Save this as MyFirstScript.sud file in your Unreal project's Content directory somewhere. If you have auto-importing enabled you'll get a prompt saying that source content changes have been detected, and offer to import them, to which you should click "Import".

You should now have 2 new assets, a "SUDS Script" asset called "MyFirstScript", and a String Table asset named "MyFirstScriptStrings":

Import Process

Next, let's test this script in the editor.