How SVNE Works
SVNE is a Luau-first visual novel engine. Story authors write scripts that call a main vnm API. The engine provides UI, saves, sprites, sounds, choices, and chapter playback, but the story itself is still regular code.
Understanding that model helps explain why VNC does not copy SVNE’s source structure.
Expected Roblox hierarchy
Section titled “Expected Roblox hierarchy”SVNE expects a fixed place layout.
DirectoryStarterPlayer
DirectoryStarterPlayerScripts
- Story LocalScript
- vnModule
DirectoryServerScriptService
- vnRunnerServer
DirectoryReplicatedStorage
- shared
- network objects
DirectoryWorkspace
DirectoryvnSystem
- images
- sounds
- themes
- settings
The main responsibilities are:
StarterPlayerScriptsholds the story LocalScript and clientvnModule.ServerScriptServiceholdsvnRunnerServer, which initializes saves, settings, chapter unlocks, and text filtering.ReplicatedStorage.sharedholds shared helpers such as debug utilities.- The network object folder holds the RemoteFunctions and RemoteEvents SVNE uses during play.
Workspace.vnSystemholds images, sounds, theme presets, feature flags, and runtime settings.
That layout makes the engine easy to drop into a place, but it also means many story systems are coupled to a specific Roblox hierarchy.
Authoring model
Section titled “Authoring model”SVNE stories are imperative Luau:
local function intro() vnm.setBackground({ backgroundName = "baseplate" }) vnm.dialog({ subject = "Narrator", dialog = "Hello, world!" })end
vnm.registerScene({ sceneName = "intro", sceneFunction = intro,})
vnm.registerChapter({ chapterIndex = 1, chapterName = "Chapter One", scenes = { "intro" },})A scene is a function. A chapter is an ordered list of scene names. Branching uses normal Luau control flow:
local choice = vnm.promptChoice({ choices = { "Red", "Green", "Blue" } })if choice == 1 then vnm.dialog({ dialog = "I like red." })else vnm.dialog({ dialog = "I picked something else." })endThis is powerful, but it requires authors to understand code structure, variable lifetime, yields, and cleanup.
Runtime flow
Section titled “Runtime flow”SVNE runs most story behavior on the client:
vnm.init()initializes player data, GUI, sounds, story saves, and roaming support.- The menu starts chapter
1for a new game. playChapter()cancels current story execution, unlocks the chapter, hides the menu, optionally shows a title card, then plays each scene in order.playScene()clears the stage, cancels the previous scene thread, and spawns the registered scene function.- The chapter loop waits until the scene thread finishes, then moves to the next scene.
- When the chapter chain ends, SVNE returns to the main menu.
SVNE uses task threads as the story execution engine. A scene finishes when its function returns.
Dialog and choices
Section titled “Dialog and choices”vnm.dialog() controls the dialog box, typewriter text, portrait selection, scroll sounds, sprite emphasis, text cues, and advance behavior. If waitForAdvanceInput is true, the function yields until the player advances. If false, the line continues automatically.
vnm.promptChoice() creates choice buttons, waits for a selection, optionally stores the selected index in a story variable, and returns the selected number to the scene function.
This makes authoring compact, but the flow is hidden inside code. It is difficult to inspect the full branch graph without reading and mentally executing the script.
Sprites and assets
Section titled “Sprites and assets”SVNE resolves assets from Workspace.vnSystem by name. Sprite images are usually ImageLabel templates under vnSystem.images.sprites; backgrounds, portraits, BGM, SFX, GUI sounds, and scroll sounds live in neighboring folders.
Sprite behavior includes:
- cloning an image template into the stage,
- optional auto-positioning,
- emphasis and deemphasis,
- transition-in and transition-out animations,
- sprite methods such as
setImage,reposition,resize,jump, andshake.
This gives authors direct power, but sprite setup depends on correctly named objects and template instance properties.
Saves and loading
Section titled “Saves and loading”SVNE save data is scene-granular. A save slot records:
- chapter index,
- scene index,
- timestamp,
- story variables,
- current background.
The built-in save UI supports up to 100 slots. Slot 1 is treated as autosave. Loading restores story variables and resumes from the start of the saved scene, not from the exact line or runtime state inside the scene.
Persistence uses a player data table, periodic saves, and a save on player leave.
Main limitations to know
Section titled “Main limitations to know”- The story graph is implicit in code.
- Many story failures are spelling, ordering, or cleanup mistakes.
- Saving resumes from scene starts, not precise node checkpoints.
- Story execution is heavily client-driven.
- Custom behavior often means editing or extending the same runtime scripts users depend on.
- Long scenes are harder to maintain because save/load happens at scene boundaries.
SVNE is valuable because it proved the feature set Roblox VN authors want. VNC keeps that feature target, but changes the authoring and runtime architecture.