Unity Plugin Changelog
New updates and improvements to the StoryFlow plugin for Unity.
Unity Plugin v1.3.1
Dialogue Rollback, Localized Overrides & Loop Fixes
Adds opt-in dialogue rollback with a Back control and localized Data Asset overrides. Brings loops, array nodes, variable scope and error reporting in line with StoryFlow Editor's own runtime, including For Each loops that stopped after their first element. Required for projects exported from StoryFlow Editor versions that localize Data Asset overrides.
What's New
New Features
-
Dialogue Rollback: Enable Dialogue Rollback in StoryFlow Editor’s project settings, export again and the plugin keeps a bounded history of earlier dialogue steps.
GoBack()on the dialogue component returns to the previous interaction and restores story globals and locals, script and loop positions, once-only choices, character values, Data Asset runtime writes and the story’s random stream. The supplied dialogue UI base has an optional Back Button field, andSetBackAllowed(bool)adds your own enabled condition. Rollback is off by default and costs nothing while it is off -
Block Rollback: Call Block Rollback, or place the Block Rollback node in a story graph, before work that cannot be undone, such as granting an achievement or writing to a server. It clears the retained history, so Back cannot cross that point
-
Localized Data Asset Overrides: A string a child Data Asset overrides is now translated like the declared value it replaces. Fields that opt out of localization in StoryFlow Editor stay as authored
-
Configurable Script Nesting Limit: The maximum depth of Run Script calls follows the project’s setting in StoryFlow Editor, so the plugin stops a runaway chain at the same depth the editor does
Improvements
- Error Reporting Matches StoryFlow Editor: A missing script, a missing flow, a Run Flow with no Entry Flow and a Start node with nothing connected now raise the same errors the editor shows
Bug Fixes
-
For Each Loops Stopped After Their First Element: A loop whose body ended on an unconnected Random Branch, Switch On Enum or Branch output, a Block Rollback node, an empty flow, an empty Loop Body or a Run Script with nothing connected after it stalled on the first element and never reached Completed. The loop now moves on to its next element, whichever node the body ends on
-
Long Loops Were Cut Off: A node-count guard stopped loops over a few hundred elements. The guard now counts nodes since the last loop step, so long array and map loops run to the end
-
For Each Followed Its Array While Looping: Adding to an array inside its own For Each body kept extending the loop. A loop now iterates the elements it had when it started
-
Set Array With Nothing Wired Emptied the Variable: A Set Array node whose array input is not connected now leaves the variable as it is
-
A Dead End Left the Line Refusing Input: Choosing an option that leads nowhere left the dialogue unable to accept another choice. The current line stays usable
-
Exit Flows With No Route Returned to the Caller: A called script that ends on an exit route nobody connected now stays in the script instead of returning through the default output
-
End Inside Nested Flows Stalled: An End reached inside nested flows of the starting script now ends the story
-
Variables Sharing a Name Across Scopes: A local and a global variable with the same name could be confused. The node’s own scope now decides which one it reads and writes, and change events report the right scope
-
Unwired Run Script Array Parameters: An array parameter left unconnected now passes an empty array, as it does in StoryFlow Editor, instead of the called script’s default
Unity Plugin v1.3.0
Data Assets, Localization & Audio-Driven Lip Sync
StoryFlow Editor Data Assets can now drive dialogue and game code in Unity, with inherited values, runtime changes and save support. This release also adds stable character IDs, project-wide localization and a lip sync component for ARKit-style facial blendshapes, including Synty Sidekick faces. Save slots move to the unified state format, while older Unity saves remain readable.
What's New
New Features
-
Data Assets Arrive With the Project: Import a StoryFlow Editor export containing
.sfdData Assets and the plugin creates assets for them, including parent relationships and referenced media. A child reads the closest value in its inheritance chain until it overrides that value. Assets can be found by stable ID or by a unique display name, so game code can use data that is not referenced by a dialogue node -
Read and Write Data Assets in Dialogue: Get Data Asset, Get Data Asset Variable and Set Data Asset Variable nodes bring authored data into value chains and story logic. A boolean Data Asset value can control whether an option appears. Array operations can change an asset’s array during play, and writes live in session state rather than altering the imported asset
-
A Data Asset API for Game Code:
StoryFlowManagerandStoryFlowComponentprovide typed getters and setters for bool, int, float, string and enum values.FindDataAssetlocates an asset,GetDataAssetVariableNameslists its declared variables andGetDataAssetVariantreads arrays and maps. Container setters can replace a declared array or map, with type checks before a write is accepted. These methods work outside an active dialogue too -
Data Asset Changes Survive Save and Load: Save slots and
ExportStateinclude values changed during the current session. Loading a save restores those changes, while a reset returns to the imported values. The state format also carries global, script and character state through one save path. Saves from earlier Unity plugin versions still load; saves written by this version cannot be read by an older plugin -
Stable Character IDs: Current StoryFlow Editor exports include a character index, and dialogue and character-variable nodes resolve characters by ID when one is available.
GetCharacterById,GetCharacterVariableByIdandSetCharacterVariableByIdlet game code keep a character binding when its file is renamed or moved. Older exports and path-based calls remain supported -
Project-Wide Localization: Import
localization.jsonwith the project to translate authored dialogue, character names and declared Data Asset strings. UseStoryFlowManager.GetLanguages()to build a language menu,SetLanguage()andGetLanguage()to change or read the selection andOnLanguageChangedto refresh your own UI. An unknown code is rejected without changing the current language. Runtime-written strings, Data Asset overrides and identifiers stay as authored -
Audio-Driven Lip Sync: Add
StoryFlowLipsyncto a character face and bind it to a StoryFlow dialogue component and character ID. It analyzes playing dialogue audio and drives existing ARKit-style mouth blendshapes without a per-line timing track or face-tracking hardware. The built-in poses support Synty Sidekick faces, including modular faces under a shared Face Root. AStoryFlowVisemeMapcan map the poses to other blendshape names. Strength, sensitivity, jaw bias and smoothing can be tuned for the voice and rig, and a manual audio source can be supplied for playback outside the dialogue component
Improvements
-
Data Asset Values Stay Current After Sync: Re-importing a project refreshes the values used by scripts and game code in the same session. The first import after upgrading may refresh existing StoryFlow assets once so they gain the new Data Asset and character data; later imports leave unchanged assets alone
-
Imported Media Resolves Across Scripts: Image and audio values referenced by Data Assets are available from the project’s shared media pool, even when the current dialogue script did not mention them
-
Lip Sync Follows the Actual Voice: The face follows the active line’s audio, keeps moving if that audio continues after dialogue text ends and returns to rest when playback stops. It also re-finds facial meshes that a character customization system replaces during play.
LevelandRawPeakreadouts help tune quiet or loud recordings -
Declared Variable Names Are Available to Nodes: Get Data Asset Variable Names returns the names declared along an asset’s parent chain, including inherited variables
Bug Fixes
-
Option Conditions From Multi-Output Nodes Work: A condition wired to a particular output of Run Script or another node with several outputs now reads the connected output rather than an unrelated cached value
-
Character Names and Portraits Return After Loading: A save that changed a character’s built-in Name or Image now restores those fields along with its other variables
-
Data Asset Reads and Saves Keep Their Values: Array and map reads return independent values, and writes or a save/load round trip no longer leave the runtime using an older copy of a Data Asset value
-
Localization Keeps Authored Text Separate: Switching languages does not turn runtime values or identifiers into translation keys. Character display names follow the selected language when character records are refreshed, and language-change callbacks arrive in the correct order
Breaking Changes
- Direct Save Helper Calls Need Data Asset Arguments: Code that calls
StoryFlowSaveHelpers.SaveorSaveAsyncdirectly must pass the Data Asset seed and current session values after the existing arguments. Calls throughStoryFlowManager.SaveToSlotorExportStateare unchanged and provide those values automatically
Unity Plugin v1.2.2
Player Build Fixes, Incremental Import & Version Control Support
Fixes imported projects going missing in player builds and Windows syncs recreating every asset, which silently broke every scene reference and inspector assignment pointing at them. Imports now rewrite only what changed, check media and assets out of Perforce or Plastic before writing them and report per-file failures instead of aborting, and dialogue nodes can fire tag events.
What's New
Bug Fixes
- Imported projects not found in player builds: imported project assets lived in a plain
Assetsfolder with nothing referencing them, so Unity stripped them from every build and dialogue failed with “no StoryFlow project found” even though play mode worked (the editor-only AssetDatabase fallback masked the gap). Every import and live sync now finds or creates theStoryFlowSettingsasset inAssets/Resourcesand points its Default Project at the imported project. That settings asset ships in every build and pulls the project and all of its scripts, characters and media in through the reference. An existing assignment to a different project is left untouched with a warning, and a settings asset placed outside aResourcesfolder warns that builds cannot load it there - Every live sync on Windows recreating imported assets instead of updating them:
Path.Combineleft the separators already inside its arguments alone, so an output folder combined with an exported relative path producedAssets/StoryFlow\media/hero.png. Unity’s AssetDatabase resolves forward-slash paths only, so the importer concluded each existing asset was new and wrote a fresh asset over the occupied path. Script, character and media assets got new GUIDs on every sync and any scene reference, inspector assignment or startup script link pointing at them silently went null. Every path handed to an AssetDatabase API is now normalized to forward slashes - One unwritable file costing the entire sync: the importer had no exception handling, so a locked texture threw out of the copy, unwound past the single save at the end of the run and left nothing saved and every remaining script, character and media file never attempted, reported as a raw exception naming no file. The inverse failed quietly: a read-only
.assetfailed insideSaveAssets, which swallows per-file errors, and live sync still logged “Import complete” over stale data. Each media copy and each asset save is now attempted on its own. A failed file is skipped rather than fatal and the next sync retries it - Media copies failing on every sync under Perforce and Plastic: Unity checks out anything it writes through the AssetDatabase, but the media this importer writes goes through
File.Copyand bypasses that, so under a provider that marks unopened files read-only every image and audio clip in the output folder failed with an access denied error that never mentioned checkout. With a provider configured, an existing destination is now checked out withAssetDatabase.MakeEditablebefore the copy and a newly created file is marked for add afterwards, so it does not sit unversioned next to versioned siblings. A refused checkout fails that one file with a message saying so and a failed add is only a warning. Unchanged media is compared before any of this happens, so a normal sync generates no checkout traffic at all - Read-only script assets rewritten and version controlled edits lost: measured against an editor whose Perforce server was stopped, a sync left a submitted, read-only script asset modified on disk with its read-only attribute stripped while Perforce still had the file unopened, so the change would have disappeared at the next sync or revert with nothing to show it existed.
SaveAssetIfDirtydoes not refuse a read-only.asset: it clears the attribute, writes the file and reports success. Writability is now settled before the asset is marked dirty, so a refused asset is never marked and no later flush (editor shutdown flushes everything dirty) can carry it to disk behind the refusal. The next sync retries it. This covers both a provider that will not check the asset out and a read-only file with no provider to ask, including a provider that is configured but offline - Global and character image and audio variables falling back to defaults: a global Image variable wired into a Set Character Variable node showed the character’s default portrait in Unity even though the editor preview was correct. The importer read only the
variablesandstringssections ofglobal-variables.jsonand never itsassetssection, so keys likeasset_image_5were absent from every resolved asset pool. Custom image and audio character variables and character map values had the same gap incharacters.json. Both files’ asset sections are now imported into the project’s resolved asset pool, which is rebuilt each import so removed assets leave nothing stale behind.GetCharacterPortraitalso falls back to the character’s baked portrait for the current image, so it stays reliable when a key is not in a pool {charVar.Name}rendering as literal placeholder text: reaching through a character-type variable to a field on the character it points to, for example{player1.Name}, printed the placeholder verbatim in Unity while the editor runtime resolved it. Character-type variables now resolve their inner fields,{Character.Name}is matched case-insensitively and string-typed character variable values resolve through the string table, for parity with the editor runtime- Assets removed or renamed in the editor still resolving in Unity: a script’s resolved asset pool was only ever appended to, so an asset removed from a script, or renamed, kept its old entry for the life of the project, still pointing at whatever it used to resolve to. The runtime went on finding it. Each script’s pool is now emptied and repopulated on every import, the way the project’s pool always has been, so removing an asset in the editor removes it in Unity on the next sync
- Exported asset paths able to write outside the output folder: asset paths come from another tool and can be hand-edited, but were trusted, so a path containing a
..segment resolved through the output folder and landed a raw file copy outside it, over a file nothing in the project pointed at. Both media importers now refuse such a path, report it by name and carry on with the rest of the import
New Features
- Dialogue tag events: a dialogue node tagged in StoryFlow editor 1.6.0 or newer now fires
OnDialogueTagReached(C# event) andOnDialogueTagReachedEvent(inspector UnityEvent) once per tag, in authored order, after the dialogue update broadcast, matching the editor’s On Dialogue Tag Reached semantics. The current line’s tags are also exposed onStoryFlowDialogueState.Tags. Tags fire only on a fresh entry via an edge: re-rendering the current line (variable changes, array set refreshes) never re-fires them, revisiting the node later does. The tag list is snapshot before any event fires, so a handler that advances or stops the dialogue mid-loop is safe. Tag strings pass through untouched, and untagged nodes and older.sfefiles without the field behave exactly as before OnCharacterImageChangedevent: fires when aSetCharacterVarnode changes a character’s built-in Image field, passing the character path and the resolved Sprite. Lets non-speaker UIs (background characters, portraits that change without dialogue) update without waiting for a Dialogue node to re-render or callingGetCharacterPortraitby handOnExecutionSettledevent: fires once when a synchronous run of nodes drains, meaning the processing loop reached a dialogue awaiting input, an End node or a dead end. Because Set* nodes execute in a single batch, save systems, debug overlays and character reactions can react once to a finished sequence of variable and character changes instead of once per change mid-sequence
Improvements
- Sync only rewrites what changed: every live sync and manual import used to rewrite everything. Each media file was copied with overwrite and reimported with ForceUpdate, and each script, character and project asset was re-serialized whether or not a byte differed, which on a project of any size meant seconds of editor stall per sync, a texture recompression for every image and a version control diff on every file in the output folder for a one-word dialogue edit. Assets now carry a hash of their source together with what they actually ended up holding and are written only when it changes. Media is compared by length and then by content before copying, and a file referenced by several scripts is settled once per import instead of once per reference. Resolved references are certified by GUID as well as path, so deleting the imported media folder in the Project window and syncing again still rebuilds it properly. A hash is recorded only after the save reaches disk, so a failed write is retried on the next sync rather than skipped forever
- First sync after upgrading rewrites every asset once: existing imported assets carry no recorded source hash, so the first import or live sync after installing 1.2.2 writes every script, character and project asset once and records their hashes, which under version control is one diff per asset. Unchanged media is compared by content and is not recopied. Every sync after that only touches what actually changed
- Import failures are reported per file: imports now report how many files were written, were already up to date and failed, with one line per failure naming the file and the likely cause (read-only or checked in, path too long, open in another application) alongside the framework’s own message, instead of Unity’s bare “Access is denied”. The importer writes a single console error listing every file it could not write, and live sync’s log, the import window’s status box and the project asset’s Re-Import dialog all check the report before claiming success, so no log says “Import complete” while a file is still stale. Failures are counted once per file, however many scripts reference it.
StoryFlowImporter.ImportProjectgained an overload that returns aStoryFlowImportReportalongside the project asset and takes an optionalforceflag, and the existing two-argument overload is unchanged - The project asset’s Re-Import button now forces a full rewrite: that button is reached precisely when something on the Unity side is wrong, and the incremental skip compares against what the last import recorded, so it cannot see an asset edited or damaged since. Re-Import now rewrites every asset and media file past the skip checks and re-records the hashes, so the next ordinary sync goes back to skipping. It stays a full rewrite even when copying media into a build directory under
Assetssets the package’s own postprocessor off mid-run. Live sync, the import window and the auto re-import postprocessor stay incremental - Editor menu moved under Tools: Import Project and Live Sync now sit at Tools > StoryFlow instead of a top-level StoryFlow menu, alongside other editor tools. The Add Component category stays StoryFlow, and the README and the no-project error messages point at the new location
- Player builds warn early when no project will be discoverable: a build preprocess check now warns when a project contains StoryFlow project assets but none is anchored for the player, the case that used to surface only as a runtime failure. It warns and never fails the build, since a scene reference also works and cannot be verified cheaply. Runtime discovery reads
StoryFlowSettings.DefaultProjectfirst and retries while no project is assigned instead of giving up after the single startup attempt, so projects that only become loadable later (references in later-loaded scenes, addressables) are found. A scene-placed manager that loses the duplicate race hands its assigned project to the surviving instance before being destroyed, and the missing-project errors give build-specific guidance instead of pointing at editor menus that do not exist in a player - The package no longer generates files inside itself: several packaged files shipped without a
.meta, so every editor minted its own and gave those files a different GUID in every project that installed the package, and a leftoverCHANGELOG.md.metawas deleted on each import and restored by the next checkout. Nothing is known to break from it, since those sources are referenced by type rather than by GUID, but a package’s GUIDs are part of what it ships. Every packaged file now ships its.meta, and the changelog archive moved tochangelogs~, which Unity’s importer ignores in the same way it ignoresSamples~, so it no longer appears in the Project window or asks for meta files
Unity Plugin v1.2.1
Typed Map Get/Set API
Adds typed get and set methods for map variables on StoryFlowComponent, so game code reads and writes maps as native Dictionaries without unpacking StoryFlowVariant.
What's New
New Features
- Typed map get/set API: read and write map variables from C# as a native
Dictionarywithout unpackingStoryFlowVariant. Eight typed getters cover the supported key and value combinations:GetStringToBoolMap,GetStringToIntMap,GetStringToFloatMap,GetStringToStringMapand the integer-keyGetIntToBoolMap,GetIntToIntMap,GetIntToFloatMap,GetIntToStringMap, each returning aDictionary<TKey, TValue>. TheStringTo*getters read both string-keyed and enum-keyed maps, and*ToStringMapresolves string and enum values through the string table while returning image, audio and character values as raw asset keys - Typed map setters:
SetStringToBoolMap,SetStringToIntMap,SetStringToFloatMap,SetStringToStringMapand the matchingSetIntTo*Mapmethods write a wholeDictionaryinto a map variable. Writes fireOnVariableChangedand live-refresh the active dialogue. A type mismatch logs a warning and leaves the variable untouched. Passing a null dictionary clears the map GetMapKeysInOrder: returns a map variable’s keys as aList<string>in insertion order, the deterministic way to walk a map’s entries. Every map accessor takes an optionalglobalflag to target global variables
Unity Plugin v1.2.0
Map Variables, Modulo Nodes & Save/Load Fixes
Adds full map variable support with all map node types, forEachMap iteration, a public GetMapVariable API and map save/load, introduces modulo and moduloFloat nodes and fixes array variables not surviving save/load along with several array and character variable execution bugs.
What's New
New Features
- Map variables: full support for the editor’s map variable type. Maps preserve insertion order, support any key and value type combination and can be declared on projects and scripts. The importer parses map variables and their default entries from synced script and project data
- Map nodes: all map node types now execute:
getMap,setMap,getMapValue,setMapValue,hasMapKey,mapSize,mapKeys,mapValues,removeMapKeyandclearMap.mapKeysandmapValuesproduce arrays that plug into the existing array nodes,getMapValueexposes anisValidoutput alongside the typed value and read nodes evaluate lazily inside condition and value chains setMapaliasing:setMappoints the target variable at the source variable’s live map storage rather than copying it, matching the editor runtime. Mutators (setMapValue,removeMapKey,clearMap) modify the origin map in place so every aliased variable and downstream chain observes the change.runScriptoutput sources are snapshotted instead, never aliasedforEachMaploops: iterate over map entries with key and value outputs on each iteration. The loop walks a snapshot of the entries taken when it starts, so mutating the map inside the loop body does not affect iterationGetMapVariable(name, global): new public method on StoryFlowComponent that returns a map variable’s entries asList<StoryFlowMapEntry>in insertion order. String, enum, image, audio and character values are resolved through the string table automatically while keys stay raw. The returned entries are deep copies, so game code can never corrupt aliased map storage- Maps in
RunScriptports: map variables pass throughrunScriptinput parameters and return through output parameters like every other variable type - Map save/load: global map variables round-trip through save slots, including entry order. The save format version is unchanged and existing saves load exactly as before
- Modulo nodes: new
modulo(integer) andmoduloFloatnodes for remainder math. Both return 0 when the divisor is zero, consistent with the divide nodes
Bug Fixes
- Fixed array variables not surviving save/load: the save path serialized array variables through the scalar
ToString()path, writing garbage values that loaded back as empty arrays. Arrays are now written as proper JSON arrays in the same dialect the importer uses, numeric elements round-trip under comma-decimal cultures and parse failures log a warning instead of being swallowed. Scalar save data is byte-identical and legacy saves load exactly as before - Fixed
set*ArrayElementandremoveFrom*Arrayreading the wrong inline data fields: the export dialect renames the inlineindexandvaluefields on these nodes, so unwired index and value inputs read empty fields and the operations targeted element 0 or wrote default values. All array element setters, appenders and removers now read the correct exported field names - Fixed
setCharacterVarsilently dropping writes to array character variables: array values were coerced to scalars, discarding every graph write to an array character variable. Array-typed character variables now evaluate the wired array input or inline JSON array and store a proper container copy - Fixed
setCharacterVarignoring wired image, audio and character values: scalar variables of these types resolved against the string input handle, so connected node chains were ignored. Each type now has its own typed input handle - Fixed
setCharacterVarandrunScriptoutput arrays not being accepted as array sources in evaluator chains, so forEach loops and array nodes can consume them directly - Fixed unwired
get*ArrayElementgetters always reading element 0 instead of falling back to the node’s inline index - Fixed
setBackgroundImagenot being usable as an image source in value chains - Fixed
stringToEnumpassing invalid values through: the node returned its raw string input verbatim, so non-matching or empty inputs produced invalid enum entries. It now validates against the downstream enum’s values list and falls back to the first enum value when nothing matches - Fixed multi-output source nodes (
forEachMapkey and value,getMapValueisValid,runScriptoutputs) returning the wrong output when evaluated through dual-input helper paths, because the source handle was not propagated during evaluation
Improvements
- Execution traces no longer log NODE and EDGE lines for start nodes, matching the editor’s HTML runtime so cross-runtime trace comparisons diff 1:1
Unity Plugin v1.1.2
Array Setters, Character APIs & Forward-Compatible Dispatch
Adds public Set/Add array variable setters, character portrait and live-update APIs, an opt-out for the built-in fallback UI, and makes evaluator chains and node dispatch forward-compatible with newer script node types.
What's New
New Features
Set*ArrayVariablesetters — new public methods on StoryFlowComponent for replacing array variables from C# at runtime:SetBoolArrayVariable,SetIntArrayVariable,SetFloatArrayVariable,SetStringArrayVariable,SetEnumArrayVariable,SetImageArrayVariable,SetAudioArrayVariable,SetCharacterArrayVariable. Each broadcastsOnVariableChangedand re-renders the current dialogue so option visibility and text interpolation refresh automaticallyAdd*ArrayElementappenders — new public methods on StoryFlowComponent for appending a single element to an array variable:AddBoolArrayElement,AddIntArrayElement,AddFloatArrayElement,AddStringArrayElement,AddEnumArrayElement,AddImageArrayElement,AddAudioArrayElement,AddCharacterArrayElement. Match the in-graphaddTo*Arraynode semantics and initialize the underlying list when called on a fresh variable- Character query APIs —
GetCharacter(path)returns the liveStoryFlowCharacterData,GetCharacterVariables(path)lists the custom variable names on a character, andGetCharacterPortrait(path, assetKey = "")resolves a Sprite using the character’s own resolved-asset pool before falling back to the standard script then project cascade. Useful for rendering multi-character UIs without inspecting the dialogue state GetCharacterArrayVariable(name)— new public method that reads a script or global character-array variable and returns the contained character paths as aList<string>, ready to pass toGetCharacter,GetCharacterVariableandGetCharacterPortraitOnCharacterVariableChangedevent — new event on StoryFlowComponent that fires whenever aSetCharacterVarnode mutates a character’s built-inNameorImagefield or one of its custom variables. Fires alongsideOnVariableChanged, not instead of itBuiltInUIStyle.None— new value on theBuiltInUIStyleenum. When set onStoryFlowComponent.UIStylewith noDialogueUIassigned, the plugin skips the auto-created fallback UI entirely so game code can drive rendering through the C# events.DefaultandPortraitcontinue to spawn the built-in fallback as beforeGetCharacterVariablenow also returns the built-inImagefield (current portrait asset key), symmetrically withName
Bug Fixes
- Fixed
*ArrayContainsandFindIn*Arrayevaluators ignoring the node’s inlinevaluefield — when the array input was connected but the value input was left unwired, the evaluators followed the array edge instead of reading the inline value, causingBoolArrayContains,IntArrayContains,FloatArrayContains,StringArrayContains,ImageArrayContains,AudioArrayContains,CharacterArrayContainsand the matchingFindIn*Arraynodes to always returnfalse/-1 - Fixed
FindInputEdgeprefix fallback returning the wrong edge for short-prefix lookups — a lookup forstringon a node with only astring-array-1edge incorrectly resolved to the array edge, with the same problem forbooleanvsboolean-condition/boolean-array-1andintegervsinteger-index. The fallback now requires the trailing segment to be either a purely numeric option ID (e.g.string-2) or a single literal token without an internal hyphen (e.g.string-array-array), so forEach loops and inline-value fallbacks resolve the correct edge - Fixed stale integer and float caches surviving a public
Set*ArrayVariableorAdd*ArrayElementcall — option visibility conditions that comparedarrayLengthorfindIn*Arrayresults now see the new values on the immediate re-render instead of the previous pass’s cached results
Improvements
- Unsupported node types in evaluator chains (boolean, integer, float, string, enum, array) no longer return a silent default — the plugin now logs a one-shot
[StoryFlow] Unsupported node typewarning per node per dialogue run, so scripts authored against a newer editor build surface the mismatch instead of quietly flipping branches or storing zeros - The node dispatcher no longer halts when it encounters an unknown node type — it logs a warning and follows the default outgoing edge, so newer scripts keep running on older plugin builds rather than stalling at the first unrecognized node
Unity Plugin v1.1.1
Array Variable API & String Localization Fix
Adds public GetArrayVariable method for reading array variables from C# and fixes GetStringVariable returning raw string table keys instead of localized text.
What's New
New Features
GetArrayVariable(name, global)— new public method on StoryFlowComponent that returnsList<StoryFlowVariant>for any array type (string, int, float, bool, enum, image, audio, character). String and enum values are resolved through the string table automatically
Bug Fixes
- Fixed
GetStringVariablereturning string table keys instead of localized text — the method now resolves values through the string table before returning, so callers get the actual displayed text rather than internal keys likestr_0
Unity Plugin v1.1.0
Data-Only Sync, Portrait UI & Execution Fixes
Adds support for data-only WebSocket sync (skip asset copying for fast iteration), a new Portrait dialogue UI with 2D sprite rendering, fixes asset serialization on first import, and resolves multiple execution issues with RunScript, arrays, and variable access.
What's New
New Features
- Data-only sync support — when the StoryFlow Editor syncs with “Data Only” enabled, the plugin reuses previously imported assets from the Unity project instead of requiring source files in the build directory, enabling fast script-only iteration without re-copying images and audio
- Added
StoryFlowRuntimeUIPortrait— alternative built-in dialogue UI that renders background and character images as 2D SpriteRenderers in world space instead of UI Image components. Select via the newUI Styledropdown on StoryFlowComponent (requires orthographic camera) - Added
BuiltInUIStyleenum on StoryFlowComponent to choose between Default and Portrait built-in UI styles when no custom DialogueUI is assigned - Imported sprites are now configured as Single mode with Full Rect mesh and Bottom Center pivot, preserving transparent areas used for image positioning
Bug Fixes
- Fixed assets not loading on first import —
AssetDatabase.CreateAsset()is now called after all data is set on ScriptableObjects, ensuring the first disk write contains the full serialized state. Previously, first import after deleting the output folder produced empty script assets that required a second sync to fix - Fixed
PlayAudionot resolving audio assets from character or project resolved assets - Fixed
SetCharacterVarwith Image type not evaluating connected node chains for the value - Fixed media variable evaluation (
GetImage,GetAudio) not checking all asset resolution sources - Fixed
RunScriptoutput parameters not passing return values back to the calling script - Fixed array
Push,Pop,RemoveAt, andInsertoperations not correctly modifying the source array - Fixed
ForEachIntLoopnot returning the current element value via the source handle - Fixed
forEachloops not clearing boolean evaluation caches between iterations - Fixed character variable arrays not being accessible as forEach loop sources
- Fixed variable access (
GetBoolVariable,SetBoolVariable, etc.) failing when called outside of active dialogue - Fixed character variable lookup failing due to variables being keyed by internal ID instead of display name
Improvements
- Added execution trace logging (
[SF-TRACE]prefix) for node processing, edge traversal, variable changes, and script calls — matches the trace format used by the Godot and Unreal plugins for cross-runtime comparison - LiveSync port and output path now persist across Unity editor restarts via EditorPrefs
- Removed
CreateAssetMenuattributes from StoryFlow asset types to prevent accidental manual creation
Unity Plugin v1.0.2
Text Block Visibility & Rendering
Fixes text blocks not appearing in dialogue by adding visibility condition evaluation and rendering support to both built-in UI implementations.
What's New
Bug Fixes
- Fixed text blocks in dialogue nodes ignoring their visibility conditions — they now use the same evaluation as dialogue options
- Fixed text blocks not rendering in the default dialogue UI and the runtime fallback UI — both now display text blocks as non-interactive labels above options
Unity Plugin v1.0.1
String Variables & Audio Fixes
Fixes string variable interpolation, array deserialization, node input matching, and audio behavior on dialogue re-render.
What's New
Bug Fixes
- Fixed string variables displaying raw localization keys instead of actual text in dialogue
- Fixed string array variables not deserializing default values, causing RANDOM nodes to return empty
- Fixed connected node inputs (e.g. SET receiving value from RANDOM) not being found due to handle suffix mismatch
- Fixed dialogue audio restarting when returning from a Set node with no outgoing edge - now uses clip reference comparison matching editor behavior
- Removed unused IsEnteringDialogueViaEdge flag
Unity Plugin v1.0.0
Initial Release
The first official release of the StoryFlow plugin for Unity, bringing full dialogue runtime support to Unity projects.
What's New
New Features
- Full Runtime Engine: Complete execution engine with full node type coverage
- StoryFlow Component: MonoBehaviour for running dialogues with full C# event-driven API
- Zero-Setup Workflow: Auto-creating StoryFlowManager, auto-project discovery, auto-fallback UI
- Variable System: Boolean, integer, float, string, enum, image, audio, and character types
- Array Operations: Full array support with ForEach loops across all variable types
- Text Interpolation: Live variable interpolation with
{varname}and{Character.Name}syntax - Script Execution: RunScript (call/return with parameters) and RunFlow (jump with exit flows)
- Character System: GetCharacterVar/SetCharacterVar with built-in Name and Image fields
- Audio Playback: Loop, reset, advance-on-end, and allow-skip support
- Background Images: Dynamic background image support with persistence and reset
- Save & Load: Slot-based persistence for global variables, characters, and once-only options
- Built-in Dialogue UI: Default uGUI dialogue UI with auto-fallback when no custom UI is assigned
- Custom Inspector: Runtime debugging directly in the Inspector
- JSON Importer: Import StoryFlow Editor projects preserving folder structure
- Live Sync: WebSocket client with auto-reconnect across play mode transitions
- Toolbar Button: StoryFlow logo button with Connect/Sync toggle
Unreal Engine Plugin