VN Framework 300+

This page is intended to guide you through the use of my Visual Novel Framework for UE4, available now on the Unreal Engine Marketplace. Watch the trailer here: https://youtu.be/bGWhDZ4N4kY

**These instructions are for versions 301 and up of the Framework, released March 31, 2021. It is compatible with versions 4.25 and up of UE4. If you are using an earlier version, go here.*

UE4 forum page: https://forums.unrealengine.com/unreal-engine/marketplace/1522971-visual-novel-framework-full-system

If you have a question about the framework, please contact me through our CONTACT PAGE.

Changes in version 301:

  • Text now displays as Rich Text. You can use <b>bold</> or <i>italic</> arguments in your text to make it bold or italic. Please note that angle brackets <> are now reserved for Rich Text purposes
  • There is now a text calibration system that prevents word from splitting on the side of the textbox during the typewriter effect. This was a very complex feature to add to the VN Framework, and the feature requires a few seconds to initially calibrate when you first start up a game
  • Argument delimiters have been normalized across the framework to be broken down in a specific order. First all args are separated by [_], then [*], then [~], then [^]. then [,].
    • Please note that if you are moving any script datatables between versions of the framework, you will need to update your SpecialEvents and SpecialEffects with the new delimiters
  • Choice code has been significantly refactored to reduce the possibility of errors within cycling and nested choices.
    • To mark a cycling choice, you should now add the _Cycle argument to the starting Choice line, rather than the DiamondbackChoice point. For example:
      Choice3*4_Cycle
  • The flow of the Scene_DT has changed. The columns for NextLevel and NextSublevel have been changed to PersistentLevel and Sublevel, now reflecting the levels for the current scene instead of the next one
  • Players can now press “L” or “Up” on the D-pad to bring up a log of text in the scene so far
  • Scenes can be in NVL mode, which displays continuous vertical text instead of the typical text box
  • There is a new feature to pause during a line. {w=2} would cause the text to pause for 2 seconds. Please note that curly braces are now reserved for this purpose, or to display variables within text
  • Text can continue on multiple rows with the “NextLine” SpecialEvent

Table of Contents

IMPORTANT CONCEPTS FOR THIS FRAMEWORK

CHARACTER SETUP

SCENE SETUP AND LAUNCH

LEVELS

OTHER

The Global_BP

I will often refer to the “Global_BP” in these instructions, and you will see it used often in the VN Framework blueprints. The Global_BP is what I call the global game instance used for this VN_Framework. It contains a great deal of customized code for saving, loading,changing levels, switching gameplay modes, and more.

If you ever need to create your own reference to the Global_BP in a fresh actor, bring up the node “Get Game Instance.” Drag the Return Value to”Cast to Global_BP.” Use the return node for the cast to pull variables or run functions through the Global_BP.

The Master Choice Log

The MasterChoiceLog is a large array stored in the Global_BP that automatically tracks every choice made in your game. By default, the length of this array is 200. You can change this length by opening the Global_BP and expanding the NewGame function. This is where a clear MasterChoiceLog first gets created.

It is important that the very first index of the MasterChoiceLog, 0, always remains 0,in order for in-scene branching to work properly. Otherwise, you can track choices however you’d like from 1-200. The options you assign to that choice will automatically get assigned a value from 1-5. If the player chooses the first option, the value 1will get saved to the assigned index of the MasterChoiceLog.

Whenever you code a choice into your game, you’ll need to enter an index value for storage in the MasterChoiceLog. I like to keep a separate document listing which story choices I’ve assigned to each index.Later, you can reference the MasterChoiceLog values to create branches or change scenes based on the player’s decisions.

Gameplay Modes

This VN Framework can be used for projects that have gameplay elements beyond just clicking-through-text. I’ve designed the modes to change automatically depending on whether a scene has started or ended. But I’ll explain the different modes to you here in case you ever want to modify them for your own purposes.

Menu Mode

This mode is enabled when a widget is created on-screen. It is triggered automatically by a family I have created under the WD_Menu_Parent. Here are a few things that happen in Menu mode:

  • A variable in the Global_BP called MenuMode? gets set to True
  • The Player Controller possesses a Pawn called the WidgetController (found in VN_Framework > Blueprints). The WidgetController contains code used to navigate my menus with keyboard, mouse, or gamepad.
  • The event MenuMode triggers for any actor with the BPI_Modes Interface

If you want your own actors to do something when Menu Mode is enabled,give them access to the Interface BPI_Modes (found in VN_Framework >Blueprints > Interfaces). Interfaces can be added to blueprints in the Class Settings menu. The BPI_Modes interface will trigger the event MenuMode when initiated.

To see more about what happens in Menu Mode, open the Global_BP and search for the event SetMenuMode.

Normal / Gameplay Mode

You can think of this as your own custom gameplay mode used to navigate the world outside of your visual novel scenes. In the example I’ve created for this VN Framework, the normal mode puts you in control of the FirstPersonCharacter (found in VN_Framework > Blueprints) and allows you to walk around in 3D space. You could change this to be your own player controller as desired.

Here is a breakdown of what happens in Normal Mode:

  • A variable in the Global_BP called MenuMode? gets set to False
  • The Player Controller possesses the FirstPersonCharacter
  • The event GameplayMode triggers for any actor with the BPI_Modes Interface

If you want to change the Player Controller used in Normal Mode, open up the Global_BP and find the variable for PlayerClass. Change this to match your custom controller. However, I recommend you only do this if you are willing to continue modifying code in the VN Framework in several other places, as a full controller switch is not inherently supported in the framework. You’ll need to search for other references to the FirstPersonCharacter in the VN Framework and replace it with your own. The FirstPersonCharacter blueprint also contains code designed to work with the VN Framework such as interaction with actors in the TouchClickActor_BP family and opening the Options menu.

If you want any of your own actors to react when Normal Mode is enabled, give them access to the Interface BPI_Modes (found in VN_Framework >Blueprints > Interfaces). Interfaces can be added to blueprints in the Class Settings menu. The BPI_Modes interface will trigger the event GameplayMode when initiated.

To see more about what happens in Normal Mode, open the Global_BP and search for the event SetNormalMode.

Scene Mode

As the name implies, this mode triggers while scenes are playing. Here’s a quick breakdown:

  • A variable in the Global_BP called ScenePlaying? gets set to True
  • The Player Controller possesses the WidgetController
  • The event SceneStart triggers for any actor with the BPI_SceneTriggers Interface

To see more about what happens in Normal Mode, open the Global_BP and search for the event SceneMode.

Preparing Scripts for Import

If desired, you can create all your scripts directly in UE4 by creating a new datatable using the ST_ScriptLines struct. Realistically, however, most writers will prefer to write scripts in their own word processing software, then upload their scripts later. Here are a few possible steps for preparing external scripts for import.

OptionA: Use a Python script I created to automatically reformat dialogue .txt files to compatible .csv files. You can download it here:  https://github.com/jgibbons25/spreadsheetAuto and here’s a video of how to use it:

OptionB: If for some reason you don’t want to use my automation script, here’s a step-by-step process for converting your script manually: https://youtu.be/bN6s24dwb2Y

OptionC: Follow the instructions below. 

For my upcoming example, I’ll assume you wrote your script in the following format:

CHARACTER1: Here’s some dialogue!
CHARACTER2: Here’s a witty comeback!

I also recommend that you break your script into individual scenes before you approach the final Import step into UE4. This ensures that each scene can be triggered independently within the VN Framework.

When conversion time approaches, take the following steps to prepare your script:

  1. Find all instances of [CHARACTER1: ] and Replace with [;Character1;Nothing;;]. The semicolons represent columns that will be blank in your spreadsheet. Note that when I searched for [CHARACTER1: ] I purposefully included the blank space, so it would get deleted by the search process. When replacing it, you should use a version of the Character name that matches the Enum Character list in your VN Framework project
  2. Repeat step 1 for every character that speaks in your script, including the Narrator
  3. Find each line break (some text editors use the [$] symbol to find line breaks) and then Replace with [;;;;\n].
  4. Save your document as a .txt file
  5. Browse to your saved file and change the suffix from .txt to .csv
  6. Open the .csv file with the Spreadsheet software of your choice
  7. Populate the column titles as depicted below:
      Speaker Expression Sound Text SpecialEvent SpecialEffect CharHorizontal CharScale 1                 Take note that the first column header is intentionally left blank; this is automatically the column used for Row Names in UE4
  8. Number the left-most column (with no header) from top to bottom (starting with 1 as shown above). This column is interpreted by UE4 as the Row Name and cannot be blank. Integers are not necessary, but recommended for convenient tracking. No matter what the Row Name, scripts will be read from top to bottom.
  9. When ready, save the document as a .csv again. It is important to use a Comma (,) as the final Field Delimiter, as this is how UE4 parses the columns into a datatable.
  10. Finally, close your .csv file. Drag it into UE4 directly or press the Import button from the Content Browser of your project. Once selected, UE4 will ask you to pick a structure. Choose ST_ScriptLines. And voila, you have imported your script!

Character Creation

When you’re ready to add your own new character to the game, there are a few steps required to define your character for the template.

You can follow the individual steps below, or follow this tutorial video of the process:

This second tutorial shows you how to trim your sprites, set up padding information for widgets, and also make sprite sheets in order to save texture memory.

Import your character sprites

This VN Framework is set up to handle a large number of sprite layers for the sake of efficiency and variety in your game. However, if you don’t want to create a character with so many layers, that’s fine,too. You can utilize as many or as few of the layers as you’d like for each character.

For reference, you can look at the sprites I used for Jessica in the Framework Tutorial. Go to VN_Framework > ArtAssets > Characters> Jessica to see all her sprites.

Before you start setting up your character layers, take a look at the starting list of Expressions available. You can find it in VN_Framework > Enums > Expressions. This is a base list you can utilize or edit as needed. If you want fewer expressions to choose from, you can delete a row by selecting the “x” on the far right. If you want to add a new expression, press the “New” button in the top right and then type in your new expression name.

Here are the layers you can use for each character expression, if you so choose:

  • BodySprite – This is the base body of the sprite. If you are using the full layer system, this body should not include clothes or the head.
  • Clothes – Character clothes go on this layer. If your character changes costumes throughout the game, this layer can be switched out for a different sprite using variables within the framework.
  • Head – This layer is for the head of the character, typically without hair. To use the system as intended, use different head sprites for different expressions.
  • HairFront – This is the main layer for the character’s hair. For most characters, this is the only layer you’ll need to show the hair. However, if the character has long voluminous hair, you might need to create a separate layer for the back hair flowing behind the clothes and body. If so, you can use the next layer…
  • HairBack – This layer goes behind the body and clothes for the back layer of hair.
  • Wildcard – This is an extra layer you might occasionally use if the other layers aren’t enough to accommodate your needs. For example, you could use this layer to add a necklace or glasses to a character. If you choose to utilize this layer, you might need to adjust its Z-order in the ParentActor and WD_Dia as needed.
  • BlinkFB – For this layer, you can create an animated Flipbook of your characters’ eyes blinking. They will automatically keep blinking at random intervals for as long as they are on screen.
  • MouthFB – You can also create a Flipbook for character mouth movement. The VN Framework is set up to use this layer for as long as the character is speaking. If there is an audio clip on the line, the mouth will keep moving for the duration of the audio clip. Please note that the in-game mouth animation moves using random frames. It doesn’t actually play the flipbook on a forward loop; it pulls the frames from the flipbook and plays them randomly.

To create a sprite, import your texture (probably a .png file) by pressing Import in the Content Browser or dragging the file in from your File Explorer. Then right-click the texture and select Sprite Actions > Extract Sprite. You can alternatively use Create Sprite, but I prefer to Extract because it automatically cuts out the transparency around each texture, which is useful for making sprite sheets.

Sprite settings

By default, the ParentActor (the base Blueprint Actor used to display each character) will set the material of your sprites to TranslucentUnlitSpriteMaterial. If you want to change this, you can adjust them in the Viewport of the ParentActor, or even create custom Child Actors for specific characters.

For best results, whenever you import a new texture for a sprite layer,go into the texture (the Texture, not the sprite). Double-click to open up the Details and change its MipGenSettings to NoMipMaps. Otherwise, the sprite layers will look blurry when they first appear in the game.

Define Your Character Layers

Now that you’ve imported your sprite layers into your project, you need to tell the Framework what to do with them. In order to do this, you’ll need to create a datatable containing your character sprite information.

The Pose Datatable

There are two main datatables you’ll create in order to tell the VN Framework what to display. The first is what I call the “Pose” datatable, and this contains information for each character pose. You can simply use Pose1 (the default) and none of the others if that’s all you need.

  1. Navigate to VN_Framework > CharData. Create a new folder for your character. Open the folder.
  2. Right-click in empty space and select Miscellaneous > Datatable. You will see a prompt to select Structure. Choose ST_PoseData. For best organization, name this something like DT_CharName_Poses_0. The “0” at the end reminds us that this datatable will be used for the default costume, value 0. You may want to create new pose datatables later for other costumes.
  3. Open your new datatable.
  4. Create a new row. To do this, find the Row Editor window, and select the Plus + sign.
  5. The Row Name is not important here (by default, UE4 for will name it NewRow). Personally, I like to change this to a number, but that is totally up to you.
  6. Under the Pose column, select from your list of Poses, which is an enum list found in VN_Framework > Enums. If you only have 1 pose, just make a row for the default, Pose1. If you want to make more poses, make additional rows for each pose.
  7. For each row, drop in your sprites to the appropriate columns for each Pose you want to use.

For each Expression using that pose, the VN Framework will pull in the sprites from the PoseDT first, then overwrite them with any layers filled in the ExpressionDT. Using this method, you don’t have to repeat as much information when building your Expressions.

The Expression Datatable

  1. Go to the appropriate folder for your character (or make a new one) in VN_Framework > CharData.
  2. Right-click in empty space and select Miscellaneous > Datatable. You will see a prompt to select Structure. Choose ST_PoseLayers. For best organization, name this something like DT_CharName_Cost0. The “Cost0” at the end reminds us that this datatable will be used for the base costume, value 0. You may want to create new expression datatables later for other costumes.
  3. Open your new datatable.
  4. Create a new row. To do this, find the Row Editor window, and select the Plus + sign.
  5. The Row Name is not important here (by default, UE4 for will name it NewRow). Personally, I like to change this to a number, but that is totally up to you.
  6. Click your new row and expand the Row Value window. Here, you will be able to edit each column in the row.
    • Pose – This is the pose your character uses for that expression. The VN Framework will use the sprites in the PoseDT first, then overwrite them with any sprites you list in the Expression DT for that expression. If you are not using the Poses, you can define all your sprites in the ExpressionDT if you prefer
    • Expression – Choose the first expression you want to define here. You will want to create a new row for each expression. I like to start with the Normal expression, which is the character’s default state.
    • For the remaining columns, drop in the layers you imported for the character as appropriate. If you have chosen not to use a layer, just leave it blank (as None). For example, if you are not using the layer system at all, just put the full character sprite in the BodySprite column, and leave the rest blank.
  7. Create a unique row for every expression in your Expressions Enum list. Even if you don’t have a new sprite for every expression, you should define the layers the framework should use if that expression is called

Creating Side Portrait Layers

In versions 1.2 of the VN Framework and above, you do not need to create separate sprites for displaying side portraits. The VN Framework will use the data you’ve supplied in the PoseDT and ExpressionDT to display the character in the side widget.

Costume Overwrites

In some cases, you may want the character to change costumes! In this situation, you can create additional datatables to hold layer information for other costumes.

To create a costume overwrite:

  1. Repeat the steps to create a new PoseDT and optional ExpressionDT using the costume layers you want to swap out. You only need to fill in the layers you want to overwrite the original costume; sprites that won’t change can remain blank
    1. Open the character’s layer DT folder (such as VN_Framework > CharData > Jessica_DTs).
    2. Create a new PoseDT (like before, it uses the struct ST_PoseData) and change the suffix to represent the new costume, such as DT_CharName_Poses_1
    3. You only need to make a new ExpressionDT if certain expressions use a different sprite than what’s listed in the PoseDT. Create a new ExpressionDT (like before, it uses the struct ST_PoseLayers ) and change the suffix to represent the new costume, such as DT_CharName_Cost1
  2. Navigate to the folder you’ve created for your character datatables. Right-click in empty space and select Miscellaneous > Datatable. You will see a prompt to select Structure. Choose ST_LayerOverwrites.
  3. Name your new datatable something like DT_CharName_CostOW (OW stands for overwrite). You can find an example in the framework at VN_Framework > CharData > Jessica_DTs > DT_Jess_CostOW
  4. Create four New Rows in the datatable. Give them the following row names:
    1. Costume (this is where ExpressionDTs for the costume go)
    2. Hair (this is where ExpressionDTs for the hair go)
    3. PoseCostume (this is where PoseDTs for the costume go)
    4. PoseHair (this is where PoseDTs for the hair go) 
      *These row names are important because the ParentActor will search for them by name when performing Overwrites)
  5. Choose an integer value to represent each costume. By default, the structure is contained to hold 5 values, and so you will see 5 columns named accordingly: Value1, Value2, etc. The default costume is already 0, so your next costume change should be 1. Under Value 1, drop in the datatable you created to hold the layer overwrites (such as DT_CharName_Cost1)

Now, you have a created a list of layers that will get overwritten if the character’s costume changes. See the section below called Define the Character and read the bullet point called RowName column to learn more about the character costume variable and how to change it.

You can repeat the steps above for the Costume, Hair, SideCostume, and SideHair layers as desired. Hair and costume layers are applied separately, so you can change the costume without changing the hair and vice versa.

Define the character

Now that you’ve set up sprites and layer datatables for your character, it’s time to put all this information together into a single character definition!

  1. Navigate to VN_Framework > Enums and open the Characters Enum list. This Enum list will contain the name of every character in your game. Find the “New” button in the top right of the window. In the new entry, type in the name of the new character and save.
  2. Navigate to VN_Framework > CharData and open the CharacterDT file. This is a master list of every character in the game and their corresponding data.
    • Row Name column: Use a unique integer in this column to associate with your character. **This number is important if you use the character costume system;** otherwise, it doesn’t really matter. If you plan to utilize the character costume system, consider the notes below:
      • The number in this column can be used to look up the character’s current costume in the Global_BP. To access this variable, go to VN_Framework > Blueprints and open the Global_BP files. Under Variables, expand the Costumes section. You will see a variable called CostumeArray and HairArray. This is an array used to hold the costume data for the game’s characters. The first index, 0, represents our Main Character, Jessica. By default, it is set to 0, and this is her base costume. To change it, this variable could be changed to 1. In that situation, the scene would look for a layer overwrite datatable to use on Jessica for costume 1.
      • I recommend setting your Main Character as 0, and continue to number the characters based on their importance (i.e. their likelihood to change costumes!). For instance, if you create a minor character with only a few lines in the game, give them a high number like 20. Reserve the lower indexes for characters who might actually change costumes.
    • Character column: select the Character’s name here from the Enum list you recently updated
  • CharActor: In most cases, you won’t need to use this, and you can leave it as None or ParentActor. As long as you have defined costume layers for your character, the SceneTemplate will use the ParentActor to display them. The exception is if you ever want to make a custom blueprint for specific characters. To do this, you could take the following steps:
  • Navigate to VN_Framework > Blueprints. Find the ParentActor blueprint.
  • Right-click the ParentActor and select Create Child Blueprint Class at the top, then name it. For instance, if you have a character named Sam, you might name the new blueprint “SamActor”
  • Open up the SamActor to create custom events or variables for that character.
  • When ready, return to the CharacterDT file, and set the CharActor to SamActor for Sam.
  • ExpressionDT: Drop in the expression datatable you created to define your expression layers here, such as DT_CharName_Cost0. If you leave this blank, the scene will not spawn a character in 3D space; it will look for a side portrait image instead.
  • PoseDT: If you created a pose datatable for your character’s poses, place it here. This is helpful for reducing the information needed in your Expression DT, and can also include padding information for displaying the sprites in widgets. But you can still leave it blank if you want to rely on the ExpressionDT or SideImage instead
  • SideImage: This is the simplest method used to display a character. It uses a static image for the side portrait instead of spawning the character in 3D space or displaying animated layers. You may want to use this for very minor characters who don’t have a full body sprite, layers, or even animations. If you already have a PoseDT defined, leave this empty, or it will try to use the static layer! Otherwise, place a static square image of the character here to be used as a side portrait.
  • LayerOverwriteList: If you created a list of overwrites for this character’s costume changes, you can drop in that datatable here (in our example, we called it DT_CharName_CostOW). Otherwise, leave it empty.
  • AccentColor: You might find this handy if you want the UI elements to change colors when different characters speak. If so, you can set their AccentColor here.
  • CloseupVertAdjust: This a variable used for the Closeup cameras within the VN Framework. Usually, you can leave this blank. If you have a very tall or short character, you might need to adjust their closeup camera position with this number.
  • CustomScale: The VN Framework uses large sprites to display characters in the game. As such, sometimes it’s difficult for all the characters to display at exactly the right proportions relative to other characters. If you realize you need a character to look slightly larger or smaller, adjust the scale here. **Use very small increments** as any variation from 1.00 will have a strong impact on character size!
  • AutoWidget?: This determines whether the character is displayed as a widget on Closeups. If you set this to True, every time you use the Closeup special effect, the character will display as a widget (this is useful if you want a cleaner image of your character without Post Processing applied). If you keep this as False, this switch won’t happen automatically. But you can still use Special Effect commands like “Widget-Zoom” to display the character as a widget, if you’d like.
  • SideWidgetPadding: (in version 1.3 of Framework) Enter X and Y values here for adjusting the placement of each character’s side portrait

Displaying Characters

Now that you actually have your character set up, you’re ready to display the character in a scene!

Here are a few different ways to display your character in a scene:

  • Spawn a ParentActor
    • Enter CharX values on a line where that character is a Speaker. Optionally, you can also enter values into , CharY and CharScale to control vertical position and scale. The default character scale should is 1, but you can zoom in using fractions such as 1.2, 1.5, etc.  If the character is not already spawned, these values together will spawn the actor as defined in the CharacterDT
  • Display a Side Portrait
    • If you defined a static Side Portrait for the character in the CharacterDT, this will automatically display if the character speaks and has no ParentActor spawned. If you defined a Side Portrait layer system, they will display in the side with the defined layers
    • If you want a character’s Side Portrait display but they are already spawned as a ParentActor, just add the word “Side” in the SpecialEffect column. This will display their Side Portrait no matter what.

To help you understand how the SceneTemplate_BP works, I’ll tell you a bit about its default operating method. When you create a line with a character speaking, the SceneTemplate_BP will first check to see whether that character has been spawned in the game as a ParentActor (or child of the ParentActor). If the character is not yet spawned, the SceneTemplate_BP will look for a number in the CharHorizontal column. If it sees a number other than 0 (such as 10), it will spawn the character at that Horizontal value. If the number is 0, it will try to display a Side Portrait of that character in the dialogue widget instead. First it will check whether you defined a static portrait for that character in the CharacterDT list. If it finds a static portrait, it will display that. If not, it will lastly look for a side portrait layer datatable. Finally, if none of these things are found, it will only show text and no character.

Defining a Scene

Every scene in the game is a datatable. To learn more about importing scenes as datatables, look at this section: Preparing your scripts for import.

Once you have a scene ready to play as a datatable, open the DT_MainScenes datatable, found in VN_Framework > Scenes. Fill out each row accordingly.

  1. Row Name — this gives the datatable a unique identifier for each row. On this column, create a nickname for your scene. For this example, we’ll use the first scene of the game, which is the “Intro.”
  2. Datatable — Here you’ll enter the actual datatable to be used for the scene from the Content Browser.
  3. NextScene — Do you want another scene to play immediately after the current scene? If yes, enter the scene’s Row Name (i.e. nickname) here, and that scene will play after the current one ends. Otherwise, leave it blank, and the game will exit VN mode after the current scene ends.
  4. PersistentLevel — If you want this scene to take place on a specific persistent level, enter it here. Otherwise the level doesn’t change.
  5. NextSublevel — If you want this scene to take place on a specific sublevel, enter it here. Otherwise the sublevel doesn’t change.
  6. CameraOverride — It is probably rare you will need to use this column, as there are many other places to control the camera. For instance, you can define what camera to use in the Special Effects column of each scene. However, if you really need to control what camera is used to launch the scene right away to override the defaults, you can enter the appropriate camera tag here.
  7. BlurAmount — The VN Framework includes code that blurs the background during scenes. By default, this is enabled by setting a scene’s blur amount to 1. You can take out the blur by setting it to 0, or increase the blur by setting this to 2.
  8. CustomCode — In most cases, just leave this as False. But as you continue to develop a large scale project, you might find instances where the code for a scene is more complicated than you can fit on the DT_MainScenes datatable. If that is the case, you can check CustomCode? to True. Access the CustomSceneCode function in your TouchClickActor_BP child to create custom code here.
  9. NVL – Setting this to True causes the scene to display in NVL mode, where text is vertically stacked across the whole screen.

Launching Scenes

Scenes can be launched in a variety of ways. Read the documentation below, or watch this full video tutorial to see the process in action:

Launch Your first scene

To launch the first scene of your game, open up the Main Menu widget,found in VN_Framework > Blueprints > Widgets > WD_Main_Menu. Find the event called StartGame. A few commands later, you’ll see a function called Force Start Scene called in the Global_BP. Enter the Nickname of your first scene (as it matches the DT_MainScenes entry you first created) into the Current Scene field. This will launch the first scene from the main menu.

From the DT_MainScenes datatable, you can string multiple scenes together by entering the appropriate nicknames into the NextScene field. You can also change Levels and Sublevels with each scene.

*Note: Any scene not launched by clicking something in the game is launched by an actor called the InvisibleSceneStarter_BP (found in VN_Framework_Blueprints > Touch-Click_BPs).

Launch in-game scenes

Sometimes, you’ll want to launch a scene from within the game, such as when interacting with a 3d object or character. To do that, follow the steps below.

  1. Find the TouchClickActor_BP, located in VN_Framework_Blueprints > Touch-Click_BPs
  2. Right-click on the TouchClickActor_BP and select Create Child Blueprint Class.
  3. Name it as you wish (for instance, YourTouchClick) and place it into your game.
  4. In the Functions panel, click Override, then select the PickLocalScene function.
  5. Now you can create custom code for the child actor to launch specific scenes. Enter the desired scene nickname into the Return Node.

In some cases, you might want to launch a scene outside of clicking on something. In these cases…

  • From the object you wish to trigger the scene, you need to create a reference to Global_BP and launch the event “Force Start Scene.” Type in a nickname for the scene in the “Current Scene” string field.

Conditional Scenes

As your story advances, you will likely want certain scenes to launch only under certain conditions. For instance, did the player already finish another event, or make a specific choice previously? You can add conditions to control what scene launches by adding code to the Pick Local Scene function, as demonstrated in the following image.

* IMPORTANT NOTE * : The PickLocalScene function should ONLY be used to figure out the nickname of the scene that should play. If you want to add Custom Code when a scene launches, do that in the CustomSceneCode function available in the Touch-Click_BP actor and set the CustomCode? boolean to True in the DT_MainScenes list.

FILLING SCENE DATATABLES

Scenes need to be created in a spreadsheet such as Excel or OpenOfficeCalc that can then be exported as .csv files. Your dialogue will typically go in the Text column, but all the other columns are also important.

ROW NUMBER

The first column holds the name of your row, and is used to organize the datatable in UE4. The first row (below the header row) should start at 1 and increment accordingly. It’s convenient to use code here via OpenOffice: change the Name Box to SUM and enter the code =ROW( )-1.Copy this box all the way down the column to automate the field. This way, it will be easy for you to rearrange and move rows later on.

*Note*: It is not actually necessary for the numbers to be exact, or even be numbers (for instance, you could enter 4b, 4c, etc). This is primarily done for organizational purposes. UE4 will display them in order from top to bottom, no matter what populates the Row Number column

SPEAKER

Here you must enter the name of the character speaking on this row. This column only accepts values from the Characters enum list, found in VN_Framework > Enums. You can leave it as None if this row contains code other than a speaking character, or Narrator if you want the text to display without any character involvement.

EXPRESSION

Here you can enter an expression for a character. This is entered as an Enumerated list into UE4, so it only accepts certain values. You can leave it blank or enter “Nothing” if you don’t want the expression to change. You can also use a row to change a character’s expression even if they aren’t speaking if you enter their name as the Speaker but leave the Text field blank.

SOUND

As you might guess, this is where sound clips go! All sound files here must be Sound Cues. By default, the sound clips are interpreted by the SceneTemplate_BP as voice acting clips. However, you can put different sounds here as needed with corresponding code in the Special Effects column.

If you want an environmental sound effect to play instead of a sound clip, just type “Sound” in the Special Effect column. This will prevent the sound from being connected to sprite mouth movement,and also the sound won’t stop when the next line starts.

You can also change the music or ambience of a scene here. If you enter”ChangeMusic” in the Special Effect column, it will change the music to whatever Sound Cue is in the Sound column. Similarly,”Change Ambience” will change the ambience.

TEXT

This is where you input the text that will display on screen while a character is speaking. You can leave it blank if you are using the row for other code, and the game will skip displaying that line.

Ina few cases, this column can take non-speaking code that is used in tandem with the Special Event column.

Text Effects

In-text Pause or Wait:

You can achieve an inline pause by putting w=time inside curly braces. Example:

  • Text: Wait a sec…{w=2} Okay, ready.
    • In that example, the text will pause for 2 seconds between “sec…” and “Okay”

Variables within Text:

You can also insert your own variables into curly braces. A built-in example would be a custom player name. In the Global_BP, there is a variable called PlayerName, set to “Jasmine” by default. So including {player} in your text would render as “Jasmine.” If you want to add player customization to this, you’ll need to set up your own code as desired to let the player change this variable.

To add your own custom variables, open the SceneTemplate_BP, found in VN_Framework > Blueprints. Find a function called CheckTextforVars. Here, you will see an area to add your own code to changing variables in {curly braces} to display as you choose.

Rich Text

The VN Framework now supports Rich Text. You can create bold or italic words by surrounding them with the angle bracket arguments, as this example shows:

  • <b>bold</>
  • <i>italic</>
Escape Characters

If you really need to show some angle brackets in your text like this “<>”, you can put an asterisk before each one to be treated like normal text. So in the text column of your scene datatable, you would actually enter “*<*>” in order to display “<>”.

Custom Rich Text

To customize your own effects, you can edit the RichTextDT datatable found in VN_Framework > Structures. But be aware that each new effect Row Name needs a version for Small, Medium, Large, and ExtraLarge text with an underscore “_” between. So if your new effect was called “yellow,” you’ll need to make “Small_yellow”, “Medium_yellow”, “Large_yellow”, and “ExtraLarge_yellow”.

Line Calibration

This Visual Novel Framework includes an intricate system designed to prevent words from jumping to another line while gradually displaying with the typewriter effect. Due to the complexity of this system and the time it takes for the text to calibrate, this feature is turned off by default.

To calibrate, each character must briefly display on the screen while the framework measures the character’s size. When the feature is on, calibration has to run just once the first time the game is played and whenever the user changes the text size or window size.

If you would like to use this feature, open the Global_BP blueprint found in VN_Framework > Blueprints. Then find the variable Text > UseLineCalibration? and set it to True.

SPECIAL EVENT

The SpecialEvent column is primarily used to control branching or choices in a scene. Think of it as the column to use if you need to jump to a different line in the script, rather than move from top to bottom.

Go to the following sections to learn more about how to use this column:

Other Special Events:

  • EndScene – Forces the scene to end, no matter where you are in the script
  • SetCL*6*1 – use this code to set a MasterChoiceLog value within the flow of the scene. Typically, this is used at the very end of the scene, to record that the player witnessed the scene
  • SetNS*Intro – Sets the next scene to the second argument, such as “Intro”
  • NextLine*auto: NextLine lets the text stay in the textbox while continuing to the next line. You can add the *auto argument to make it move seamlessly into the next line.

SPECIAL EFFECT

Here you can enter Special Effects that will happen as the scene progresses. You can put multiple values in a single Special Effects box if they are separated with the _ delimiter. For example, Wideview_Shake_Pause*2 will process all three special effects on the same line.

Listed below are some general Special Effects commands you can use as you please. I’ve also created separate explanations for effects in the following categories:

Other Special effects:

  • Achieve*[AchievementID] – This will cause a Steam Achievement to be obtained on that line, IF you have already followed all other necessary steps to utilize the Steam SDK in your game. Put the name ID of the Steam achievement after the plus sign. For example:
    • Achieve*ShunRolan
  • AssignView – Use this to add a camera to a character’s list of cameras. This causes the character to stay visible when cutting to that camera
  • Black – immediately turns screen black. Remains there until you use a “FadeIn”
  • Boom – Cause the cameras to shake briefly and dramatically, as if an explosion just went off
  • ChangeMusic – put this in special effects and put the music file in the Sound column to change the background music. If you leave the sound column blank, music will fade to nothing.
  • ChangeAmbience – put this in special effects and put the ambience file in the Sound column to change the background ambience. If you leave the sound column blank, ambience will fade to nothing.
  • Char*[Front/Back] – Forces a character to the front or the back relative to all other characters in the scene. For example, Char*Front
  • Costume[X] – When used with a character specified in the Speaker field, it will set that character’s costume to the value indicated by X. This number is the value of that costume in the character’s overwrite list. For example, Costume2
  • Delay*[Time]*[FX~Snd~Exp~All] : Delays an effect as indicated by the first and second arguments. FX delays whatever else is in the SpecialEffect Column, Snd the Sound column, and Exp is the character’s expression. For example, Delay*2*Exp makes the character change expression 2 seconds after the line starts. Enter “All” as the 3rd argument to delay all 3.
  • Destroy – this destroys the character actor whose name is listed in the Speaker column. This is handy if you want a character to move from one camera angle to another mid scene. You will need to destroy them before moving them to the new camera angle
  • Fade[In/Out]*Color*Time: The first argument fades the whole screen in or out. The second two are optional to specifiy a color and tim for the fade, such as FadeOut*White*3 (fade to white in 3 seconds)
    • FadeIn – causes the black screen to fade away. Text resumes normally during this
    • FadeOut – makes screen fade to black.
      • If put on the same line as dialogue, the fade will begin as soon as the line begins, but the player cannot continue until screen is fully black
      • If put on a skippable line (no dialogue), the previous text will remain on screen while fading to black. Script will continue once fade has finished
  • FadeInSprite – (obsolete – not necessary because characters fade in by default) Use this when a character first spawns in the scene if you want them to fade in from a given location, rather than slide in from the side
  • FadeOutSprite – Use this to make a character fade out. Their actor will be destroyed once the fade is complete.
  • Hair[X] – When used with a character specified in the Speaker field, it will set that character’s hair to the value indicated by X. This number is the value of that hair in the character’s overwrite list. For example, Hair2
  • Immediate – Used on the line of the character spawn, this causes the character to appear instantly, without a fade or slide
  • OutLeft – Make a character slide out left and then destroy its actor
  • OutRight – Make a character slide out right and then destroy its actor
  • Pause*2 : This will pause the whole scene for the amount of time listed at the end; in this case, 2 seconds. If there is no text on the line, the dialogue widget will fade out during the pause, otherwise nothing will change. By default, these pauses will be skipped through if the player clicks. But you can add one more argument, *Hard, to make the pause unskippable, such as Pause*2*Hard
  • PersX – Replace X with the index associated with that persistent variable. Marks that persistent variable as true
  • PlayerMove – use this to transport the player actor to the position of the current camera. This is helpful for any effects that are relative to the player actor position, and for a smooth transition when the scene is over
  • PushBack – This can be used on the same line a character enters a scene for the first time if you want them to appear further behind other objects in the scene. They will still appear the same size, just further back. The default space multiplier is 3.3; if you want to change the Pushback amount, use can use PushBack*[new multiplier]. Example: PushBack*2.3
  • RedFlash – makes the screen flash red quickly
  • Rumble – A slow, prolonged camera shake lasting about 5 seconds, kind of like a tremor in the earth
  • Shake – Shakes the camera without any noise
  • Side – If this word is used on a line with a character speaking, this will display that character’s Side Portrait, even if they’re already spawned in the game as a ParentActor
  • Sound – Use this to play an atmospheric sound effect via the Sound column, the difference being that it won’t cut off when the next line starts
  • Speaker*[Nickname] – With this effect, you can temporarily change the name that displays in the dialogue widget while a character speaks (remains in effect until the end of that scene). For instance, if a character is truly named George, but the player doesn’t know his name yet, you could enter Speaker*??? on George’s first line. Then, every time he speaks, his name will appear as ???. If you want to change his name back to its default, enter Speaker-X on one of his speaking lines.
  • WhiteFlash – makes the screen flash white quickly
  • Widget*Zoom – use this to turn the character on that line into a zoomed-in widget display. In order for this to work correctly, make sure you’ve set up your PoseDT with padding so that it works in widgets. This effect has a few variations depending on the second word you use:
    • Widget*Base – creates a widget character at widget scale 1.0
    • Widget*Zoom – creates a widget character at widget scale 1.2
    • Widget*Zoom2 – creates a widget character at widget scale 1.4
    • Widget*Stop – destroys the widget and returns to a display of the character’s ParentActor

You can find a some additional SFX specific to cameras in the Cameras section.

CHAR X

Values entered here determine where a character is placed horizontally in the scene. Values close to 0 place them near the middle of the screen (if you enter 0, nothing would happen). Positive values move them right, negative values move them left. These values consist throughout a scene, so if you entered 45, then 45 again on another row, the character would stay in place. Numbers above 90 will start to move the character off-screen.

If you enter a value here for a character who has not yet entered the scene, this will cause them to be spawned and enter. Otherwise, it will try to move them.

If you want more than one character to be spawned at the beginning of a scene, use a row with a blank Text field to spawn them before the text starts displaying.

CHAR Y

The CharY column controls a character’s vertical placement on the screen. “0.0” value will use default placement. Negative values will move the character up. Positive values move them down.

CHAR SCALE

Here you can enter the scale of the character being displayed. Please note that this only goes into effect when the character first spawns; you cannot change their scale again unless you destroy and respawn the actor. Recommended values are between 0.5 and 2.0. 1 is of course the default scale; values below that will shrink the sprite, and values above will zoom in.

The CharScale column should always have a value assigned when first spawning a character with a CharHorizontal value.

Changing Cameras

Before you start changing cameras in a scene, you should understand a little bit about how cameras automatically work within the VNframework.

Cameras are tracked in the Scene_Template_BP using tags. By default,when you launch a scene, you do so from the player’s viewpoint. This default camera uses the tag “PlayerCam.”

Whenever you spawn a character into the game, they create their own list (held in the ParentActor) of Camera tags assigned to them. For instance, if you spawn Jessica at the PlayerCam, the first index ofJessica camera tags will be “PlayerCam.” Now let’s say you switch to a different camera (let’s say Camera2) and spawn adifferent character named David. David’s camera list will start with”Camera2.” The next time Jessica speaks, theScene_Template_BP will automatically cut to the camera at the beginning of her camera list. Therefore, you can have a scene that automatically jumps between the two characters without a SpecialEffects command in every line.

It’s also important to note that when you cut to a camera, any character NOT assigned to that camera will become invisible. This is done to prevent the player from seeing the spawned character sprites at unintended angles in 3D space, which could look very strange!

When cutting between two cameras, code in the MainCamera actor will compare the rotation of the two cameras and calculate a small slide effect to soften the cut.

If you ever want to spawn a character at a new angle within the same scene, you’ll need to destroy the previous actor first with the “Destroy” SpecialEffect command.

PLACING YOUR CAMERAS

Navigate to VN_Framework > Blueprints > Cameras to find camera actors designed to work with the VN framework. The MainCamera actor is the parent of all the other cameras. By default, it has no tag on it.

If you drag the MainCamera into a Map for use in a scene, make sure you give it an Actor Tag using the Details pane of your Editor. You can make your own camera tags, but make sure that the word “Cam” is somewhere within the tag, such as”JessicaCam.” This lets the Scene_Template_BP interpret the string as a camera command when you use it in a scene.

For convenience, you can use the child cameras (such as Camera1,Camera2, etc.) so you don’t have to make your own tags. Camera2already has the “Camera2” tag assigned to it, and so on for each child camera.

EXTRA CAMERA COMMANDS

Now that you have a basic understanding at how the cameras work, here are some additional commands you can use to create cinematic scenes!

  • Closeup – This will create a new camera in a closeup view of the speaking character on that line. The camera will continue to use the Closeup view for following lines until “Wideview” is used to pull back out. This camera is destroyed whenever the character gets destroyed.
  • Wideview – switches from a Closeup back the original view of a character
  • Handheld – start ongoing handheld camera effect
  • StopHandheld – stop handheld effect
  • CLeft – causes the camera to shift slightly to left
  • CRight – causes the camera to shift slightly to right
  • CUp – causes the camera to shift slightly up
  • CZoom – causes the camera to zoom in slightly. Note this different from “Closeup,” which creates an entirely new camera view. This is just a temporary zoom
  • CRand – Causes the camera to jump to a random new position every few seconds. Good for tense, dramatic, uncomfortable scenes
  • CReg – Returns camera to normal position
  • SS – slow slide. Add this to a camera argument to make it a smooth, slow glide from one camera to the next
  • NT – No transition. Add this to a camera argument to ensure the camera slides in with no transition at all – just a straight cut
  • ST– use this to manually set the time of the camera blend. In order to use it, you need to enter the blend time in the “Text” field, which means the rest of the line will be skippable. The second number after the first is the delay before the next text line. Enter something like:
    • 5_6 … to mean that the camera blend takes 5 seconds, and you want to wait 6 seconds before the next line fires. Enter 5_0 if you want the script to keep running while the camera is blending

PERSISTENT DATA

Persistent Data functions differently than normal save data, because it tracks permanent variables for any and all playthroughs of the game. Once a variable is unlocked in persistent data, it remains unlocked even when the player starts the game over.

You can open VN_Framework > Blueprints > Save >PersistentData to view the actor used for saving Persistent data. The Global_BP creates an empty PersistentLog with 100 boolean entries upon the game’s first launch (you can find and edit this in the Global_BP Event Init).

Typically, the persistent data would be used to track which CGs the player has unlocked or which routes they have played. For instance, you might have a Persistent value unlock when the player beats the game. Within a scene, you can add PersX (replace X with the index of your choice) to the Special Effects column to set it True.

Types of Persistent data the VN Framework tracks:

  • PersistentLog = an array of boolean values used to track a variety of persistent variables. When you create a value using PersX in a scene, this gets saved to the PersistentLog. Also, when you number your gallery CGs, these are unlocked at the corresponding index in the Persistent Log.
  • SceneLog (version 1.4+) = an array of scene nicknames the player has viewed. The VN Framework tracks this automatically and enables or disables skipping depending on whether that scene has been viewed
  • MCLPersistent (version 1.4+) = an array tracking the player’s choices. The number of the choice gets added to the index each time. So if in one playthrough they chose 2, and on the next playthrough they chose 1, the value would equal “21.”

You can use the PersistentLog to track whatever variables you’d like, but make sure you keep a tidy list of your index values so you don’t mix them up!

CG and gallery system

This VN Framework includes a template for a gallery and CG system within your game. Navigate to VN_Framework > Gallery to see assets associated with the Gallery system.

DEFINE THE CG

Open the GalleryListDT to view and edit a comprehensive list of every CG in your game. Take note of each column and what it represents.

  • RowName – The first column–which is always the Row Name–should be an integer value unique to that row. This number is important, because it corresponds to that CG’s index in the PersistentLog file. Once the player sees that CG in the game, this PersistentLog value will be set to true. After that, the player can view the CG in the Gallery.
  • Texture2D – In this column, drop in the 2D texture you want to display when that CG is called (not necessary if you provide a Sprite)
  • Sprite – (version 1.4 and up) Drop the sprite for the CG in this column. If a sprite is provided, this will take priority over the Texture2D.
  • Nickname – Give the CG whatever nickname you like, so long as it’s unique. Use this Nickname in your scene datatable when you want it to display.
  • Category – This only affects how the CG is displayed in the Gallery. You can add or detlete categories from this enum list by editing VN_Framework >  Gallery > GalleryCategory. The Gallery will automatically break the CGs into the appropriate categories to ease browsing.

SHOW IT DURING A SCENE

To display a CG during a scene, you’ll need to reference the Nickname you gave it in the GalleryListDT. Type the nickname into the Text field of your scene datatable, then type “CGstart” into the SpecialEffect column.

Example:
Text                           Special Effect
YourCG1                  CGstart

Optionally, you can add arguments to show your CG with transitions or zooms.

Transitions:

  • YourCG1*shake – The CG will appear with a shake effect
  • YourCG1*fade – The CG will fade in
  • 3 more arguments can be added to set Scale, X Pivot, and Y pivot in that order. For example:
    • YourCG1*fade*1.4*0.6*0.4 –> Sets the scale of the CG to 1.4 and the pivot x to 0.6, pivot y to 0.4 while it fades in.

Once the CG is already on the screen, you can continue to control itwith commands in the Special Effects column.

  • CGcut – use this in the Special Effects column to change the pivot point and scale of a CG. Type the 4 arguments controlling this cut into the Text field. For example:
    • 1.4*0.6*0.4*2.2
      • Argument[0], 1.4 = scale; Argument[1], 0.6 = X pivot; Argument[2], 0.4 = Y pivot; Argument[3], 2.2 = timeline length (can be left blank)
  • CGend – use this to make the CG fade out

Using Sounds

Whenever you import a sound file into your project, turn it into a Sound Cue (right-click, then select Create Cue). Once you have a Sound Cue, give it a class. The VN Framework comes with several sound classes to choose from in VN_Framework/AudioMixandClass.

  • MusicClass (not affected by reverb)
  • SFXClass (affected by reverb)
  • VAClass (affected by reverb)
  • VA_NarrationClass (not affected by reverb)

Assigning the right classes will ensure that the sounds are properly affected by the volume levels set in the Options menu.

For VA sound cues, just drop them onto the line they’re voicing (into Sound column), and the VN_Framework will know what to do with it. To change the music or ambience, put those sound cues on their own line with a special effect, either ChangeMusic or ChangeAmbience.

Branches and Choices

Scene Branches

To create a branch in a scene, you need to know which Master ChoiceLog index and value to check (the Master Choice Log is a large array that remembers every choice made in the game). When you’re ready, add the word Condition to the SpecialEvent column. Then place a line of code into the Text field of that line.

Example Condition code:
7_1_YourBranch1_YourBranch2

The above line gets interpreted by the Scene Template as: IF Master Choice Log Index 7 EQUALS Value 1, THEN jump to YourBranch1, ELSE jump to YourBranch2.

Please note that the last argument, YourBranch2, is optional. If you left that blank (just 7_1_YourBranch1), then the script would continue to the next line if your condition was false.

The variables “YourBranch1” and “YourBranch2” are simply strings that can be whatever you want, so long as they match the SpecialEvent value of the line you want to target. Just make sure to create a unique tag for every branch within the same scene.

Example:
Text Special Event
MasterChoiceLog 7 equals 1! YourBranch1

If you want this line to play for YourBranch1, put that tag in the YourBranch1 Special Event Column!

When you’re ready to diamond back from the branches, create a new tag for the diamond point, such as DiamondBranch1 (but it can be whatever string you want, as long as it’s unique). Then create a new Condition line for the jumping point. Use 0_0 as the values to check, which always return True. In order to use this properly, make sure that MasterChoice Log Index 0 always remains 0 (in other words, never use that index for a choice).

Example:
Text                                               Special Event
0_0_DiamondBranch1               Condition

As your story gets complicated, you might occasionally need to chain several conditions together. There are several ways to do this. If you want to create a branch tag that starts with the word “Condition,” you can both jump to this line and still check the text field for a condition. Alternatively, leave the last argument blank to keep moving down from one line to the next, until the script finds an appropriate jumping point.

Example:
Text                                                             Special Event
6_1_Branch1_Condition2                           Condition
6_2_Branch2_Branch3                               Condition2

Adding Choices

To add a choice to a scene, you’ll start by entering code into theSpecial Event column.

Example:
Text                                                                                              Special Event
Uh oh, I need to choose between a dog and a cat!                Choice1*5

The Text line will display on screen as normal. Meanwhile a choice will initiate. The numbers following the word “Choice” track the local and global sequence of that choice. The first value used in the example, “1,” means that it is the first choice used in that specific scene. This helps the Scene Template track multiple choices in one scene without getting lost.

The second number after the delimiter ( * ), or “5” in our example, corresponds to the Master Choice Log index you want to associate with that choice. After the player makes a choice here, that value will get permanently stored in Master Choice Log index 5.

Immediately after the choice, you need to fill the next few lines with the choices you want to appear. Mark them in the Special Event column in alphabetical order, starting with A.

Example:
Text                                                                        Special Event
Choose a dog                                                        ChoiceA
Choose a cat                                                          ChoiceB

Now you’ve assigned a dog to ChoiceA and a cat to ChoiceB.

CONDITIONAL CHOICES

If you only want a choice to appear under certain conditions, you can add code to its Special Effect column.

Example:
Condition*90*1 — This will make the choice appear only if MasterChoiceLog 90 = 1 == True. If you want it to appear when false, add *F at the end (Condition*90*1*F).

CHOICE BRANCHES

After displaying the choices to the player, the scene will then jump to the lines marked ChoiceAStart or ChoiceBStart (additional values would be ChoiceCStart, etc.) depending on what choice they make.

Example:
Text                                                            Special Event
Looks like I chose a dog!                        ChoiceAStart
I guess I’m going with a cat!                   ChoiceBStart
Either way, I’ll pick up some food.        DiamondbackChoice1

Finally, we diamond back from all choices using the string “DiamondbackChoice1” in the Special Event column, with the integer matching the scene number (for example, if this were Choice2, then use DiamondbackChoice2).

NESTED CHOICES

In some cases, you might have a choice within a choice! If this occurs, mark the second choice with _Nest at the end.

Example:
Text                                                                                                             Special Event
I chose a dog earlier, but now I need to choose its food!                  Choice2*6_Nest

To give you an idea of underlying code here, the “Nest” tag tells the Scene Template BP to skip over this choice when finding the branches for the choice above it. Please keep in mind that for a Nest choice to function properly, it MUST have its own DiamondbackChoice point. Even if you leave the diamond point Text field blank, the Scene Template BP must be able to find the diamond point in order to navigate properly.

CYCLING CHOICES

In some case, such as a detective game, you might want the player to return to the same choice and explore multiple options. I call this a Cycling choice.

There are a couple of commands used for Cycling choices.

  • Add “_Cycle” to the Choice line (Note, previous versions added this argument to the DiamondbackChoice line. It is now claimed at the initial Choice line), such as Choice1*6_Cycle. This tells the Scene Template to keep returning to the original choice point until all options have been exhausted. This command is necessary for all cycling choices.
  • When listing the player’s choices, add a choice labeled in the Special Event Column as “ChoiceExit.” This choice will only display after the player has made at least one choice, and allows them to skip the Cycling loop if they don’t want to make any more choices. The ChoiceExit is optional; if not included, the player must make every choice before continuing.
  • By default, cycling choice options have a slightly different color so the player knows they’re different. These colors can be altered in Blueprints > Widgets > WD_Choices. Find the variable AltButtonColor and change as desired.

If you want to make a specific choice necessary before continuing,you can use the ForceQ command. This is a boolean tracked by the Scene Template BP. You must set it to 1 before entering the Cycling choice, then set it back to 0 when the player makes the necessary choice. Use the following commands in the SpecialEvent column:

  • ForceQ*1 – Use this before a set of cycling questions to enable the cycle lock. This means that once you’re within a set of cycling questions, you cannot exit the cycle until the ForceQ is turned back off.
  • ForceQ*0 – Use this on the required question to enable player to exit the cycling questions

You can also make the cycle end within a choice branch by using the SpecialEvent CancelCycle. This makes the choice end normally after the choice branch is finished.

STAT SYSTEM

There is now an array of integers in the Global_BP called the StatLog. This array can be used to track stats within the game. For example, each index of the StatLog can represent a certain character, and choices made in the game could add or subtract points associated with that character.

For this example, I have chosen to track Jessica’s stats through index 0 of the StatLog. So if I want a choice to add or subtract points with her, I can add an argument to the SpecialEffect column of the associated choice. The argument should read: Stat*[StatLog index][+ or – to add or subtract][amount of points to add or subtract]. So in the example above, if I want a choice to lose points with Jessica, I would enter Stat*0-1 in the SpecialEffect column next to that choice. Currently, the minimum amount of points is clamped to 0.

To change the text message displayed in top left corner, open up VN_Framework > Blueprints > Widgets > WD_Dia, then open the function BuildStatMessage. Here you can associate certain names or messages with each index.

If you prefer that the Stat message not appear to the player, open up VN_Framework > Blueprints > Widgets > WD_Choices. Find the event ProcessStats. At the end, there is a function called StatChange; unhook the boolean for “ShowMessage?” so that it is always False.

Branch scene based on Stats

You can make a scene branch based on Stats, also. Stat conditions work similarly to Master Choice Log conditions, but they include extra arguments at the beginning of the Text field. You must include the word “Condition” in the Special Event column to process to text.

Text | SpecialEvent
Stat*1*less_8_ChoiceBStart | Condition

In the example above, if the Stat for character at index 1 of the StatLog has a value less than 8, the scene will jump to the line with “ChoiceBStart” in the SpecialEvent column.

Levels

Main_Persistent Level Explained

The VN_Framework uses a map called Main_Persistent as its primary level. Main_Persistent itself is actually just an empty level, but it can contain multiple sub-levels.

If you want to use your own full levels outside of Main_Persistent, that’s a valid option. You’ll just need to make sure they use the same Game Mode and Game Instance (Global_BP) in order to continue using the VN Framework on other maps.

Before you jump to making entirely new levels, though, considering adding your own maps as sub-levels. These can be added to the Main_Persistent level by going to Window > Levels in your UE4 editor and dragging in your map to the sub-level list.

Adding your own sub-levels to the Main_Persistent level is the easiest way to take advantage of the VN Framework.

Navigating Levels

It’s actually pretty easy to change levels and sub-levels within the VN Framework. Here are a couple different methods you can use.

  • Edit the DT_MainScenes datatable. You can find this in VN_Framework > Scenes. Whenever you define a scene here, there are optional columns for PersistentLevel and Sublevel. Enter the name of the maps you want to use for the scene here. If left empty, scene will take place wherever the player already happens to be.
  • Use a SpecialEvent command. During a scene, you can change what scene happens next by entering the appropriate command.
    • SetNS*Intro – Sets the next scene to the second argument, such as “Intro”
  • If you want the player to move to a different level or sublevel AFTER a scene ends, but there is no scene after it, you can still set that up.
    • Create a scene row just for changing levels, but leave the datatable column empty. See the example ReturnToTutorial below

Now you can put the next scene as ReturnToTutorial if you want to return to that map after a scene without another scene playing.

Rich Text

The VN Framework now supports Rich Text. You can create bold or italic words by surrounding them with the angle bracket arguments, as this example shows:

  • <b>bold</>
  • <i>italic</>

Escape Characters

If you really need to show some angle brackets in your text like this “<>”, you can put an asterisk before each one to be treated like normal text. So in the text column of your scene datatable, you would actually enter “*<*>” in order to display “<>”.

Custom Rich Text

To customize your own effects, you can edit the RichTextDT datatable found in VN_Framework > Structures. But be aware that each new effect Row Name needs a version for Small, Medium, Large, and ExtraLarge text with an underscore “_” between. So if your new effect was called “yellow,” you’ll need to make “Small_yellow”, “Medium_yellow”, “Large_yellow”, and “ExtraLarge_yellow”.

Line Calibration

This Visual Novel Framework includes an intricate system designed to prevent words from jumping to another line while gradually displaying with the typewriter effect. Due to the complexity of this system and the time it takes for the text to calibrate, this feature is turned off by default.

To calibrate, each character must briefly display on the screen while the framework measures the character’s size. When the feature is on, calibration has to run just once the first time the game is played and whenever the user changes the text size or window size.

If you would like to use this feature, open the Global_BP blueprint found in VN_Framework > Blueprints. Then find the variable Text > UseLineCalibration? and set it to True.