Skip to main content

Live Sync

Live Sync connects Godot to the StoryFlow Editor via WebSocket, letting you edit your project and see changes reflected in the engine in real time - no manual re-export and re-import after every change.

Overview

Live Sync establishes a WebSocket connection between the Godot Editor and the StoryFlow Editor running on the same machine. When you save changes in the StoryFlow Editor, those changes are automatically pushed to Godot and re-imported, keeping your in-engine project data up to date without any manual steps.

  • Real-time synchronization - edit in StoryFlow, see results in Godot immediately
  • WebSocket-based communication using ws://localhost:9000 by default
  • Automatic re-import of the full project when changes are detected
  • Built-in editor dock UI for connecting, disconnecting, and configuring the port

Editor-Only Feature

Live Sync is provided by the editor dock and StoryFlowWebSocketSync class, which lives in the editor/ folder of the plugin. It is only available in the Godot Editor and is not included in exported builds. This is intentional - Live Sync is a development workflow tool, not a runtime feature.

Architecture

Live Sync is built from two components that work together to manage the connection and synchronization lifecycle:

  • Editor Dock - The UI panel added to the Godot Editor when the plugin is enabled. It provides connect/disconnect buttons, host and port configuration fields, and a status label showing the current connection state. The dock uses a timer to call poll() at a 0.1-second interval to process incoming WebSocket messages.
  • StoryFlowWebSocketSync - The GDScript class that handles the low-level WebSocket connection, reconnection logic, message parsing, and project re-import. It receives incoming project update messages from the StoryFlow Editor and coordinates the re-import process through StoryFlowImporter.

Setup

Getting Live Sync running takes just a few steps. Make sure both the StoryFlow Editor and Godot Editor are open on the same machine.

Step 1: Open your project in the StoryFlow Editor

The StoryFlow Editor runs a sync server that listens for incoming WebSocket connections. Open the project you want to synchronize - the server starts automatically.

Step 2: Connect from Godot using the editor dock

In the Godot Editor, look for the StoryFlow dock panel. It shows a port field (default: 9000) and a Connect button. Click Connect to establish the WebSocket connection to the StoryFlow Editor running on the same machine.

Step 3: Edit and iterate

From this point on, any changes you save in the StoryFlow Editor are automatically pushed to Godot. The dock's status label updates to show when a sync is in progress or complete. You do not need to manually re-export or re-import - it happens automatically.

First Sync

On initial connection, the editor dock can request a full sync to pull the complete project from the StoryFlow Editor. This ensures your Godot project matches the current state of your story, even if you made changes before connecting.

Connection Controls

The editor dock provides the following controls:

  • Port field - The port number for the WebSocket connection. Defaults to 9000. Must match the port configured in the StoryFlow Editor.
  • Connect button - Establishes the WebSocket connection to the StoryFlow Editor's sync server.
  • Disconnect button - Closes the active WebSocket connection and stops any reconnection attempts.
  • Sync button - Manually triggers a full re-sync of the project while connected.
  • Status label - Shows the current connection state: disconnected, connecting, connected, or syncing.

You can also interact with StoryFlowWebSocketSync directly from GDScript if you need programmatic control:

GDScript
# Programmatic access to WebSocket sync
var sync: StoryFlowWebSocketSync = StoryFlowWebSocketSync.new()

# Connect with default port (9000)
sync.connect_to_editor()

# Connect with custom port
sync.connect_to_editor(9000)

# Check connection status
if sync.is_connected_to_editor():
    print("Connected to StoryFlow Editor")

# Request a full project sync
sync.request_sync()

# Set the output directory for imported files
sync.set_output_dir("res://storyflow_data/")

# Disconnect
sync.disconnect_from_editor()

Signals

StoryFlowWebSocketSync exposes three signals you can connect to for responding to connection and sync events:

  • connected() - Fires when the WebSocket connection to the StoryFlow Editor is successfully established.
  • disconnected() - Fires when the connection is lost, whether due to the editor closing, a network issue, or an explicit disconnect_from_editor() call.
  • sync_complete(project: StoryFlowProject) - Fires when a full project sync finishes. The parameter is the newly imported project resource, ready to be used by your StoryFlowComponent instances.
GDScript
# Connecting to Live Sync signals
func _ready() -> void:
    var sync: StoryFlowWebSocketSync = get_sync_instance()
    sync.connected.connect(_on_sync_connected)
    sync.disconnected.connect(_on_sync_disconnected)
    sync.sync_complete.connect(_on_sync_complete)

func _on_sync_connected() -> void:
    print("StoryFlow Live Sync connected")

func _on_sync_disconnected() -> void:
    print("StoryFlow Live Sync disconnected")

func _on_sync_complete(project: StoryFlowProject) -> void:
    print("StoryFlow project synced: ", project.title)

How It Works Internally

Understanding the internal flow helps when debugging sync issues or extending the system:

  1. Connection - StoryFlowWebSocketSync establishes a WebSocket connection to the StoryFlow Editor's sync server at the specified host and port.
  2. Polling - The editor dock runs a timer at a 0.1-second interval that calls poll() on the sync instance. This processes any incoming WebSocket messages.
  3. Change detection - When you save changes in the StoryFlow Editor, it pushes the updated project data over the WebSocket. The sync class handles "project-updated" messages (push from editor) and "pong" keep-alive responses.
  4. Re-import - When project data arrives, StoryFlowWebSocketSync passes the JSON data to the StoryFlowImporter, which processes all project files (scripts, characters, assets) and creates or updates the corresponding Godot resources.
  5. Completion - The sync_complete signal fires with the new StoryFlowProject, notifying any listeners that the project has been updated.
  6. Component update - Active StoryFlowComponent instances automatically pick up the updated project through the manager, so running dialogues can reflect the latest changes.

Reconnection

If the WebSocket connection drops unexpectedly - for example, if the StoryFlow Editor is restarted or the connection is interrupted - the sync class automatically attempts to reconnect.

  • Up to 5 reconnection attempts are made automatically, one per poll cycle
  • Connection state changes are broadcast through the connected() and disconnected() signals
  • If all reconnection attempts fail, the disconnected() signal fires and you will need to click Connect again in the dock (or call connect_to_editor()) manually

Monitoring Connection Status

Use is_connected_to_editor() to check the current connection state at any time. The editor dock's status label also updates automatically, so you always know whether Live Sync is active without writing any code.

Limitations

There are a few limitations to be aware of when using Live Sync:

  • Editor-only - Live Sync lives in the editor/ folder of the plugin and is not available in exported builds. It is strictly a development workflow tool.
  • Local only - The connection always targets localhost, which requires the StoryFlow Editor to be running on the same machine as the Godot Editor.
  • Full re-import - Each sync performs a complete re-import of the entire project rather than incremental updates. For very large projects, this may take a moment, but for most projects the import is near-instant.

Need Help?

Join our Discord community to ask questions, share your projects, report bugs, and get support from the team and other users.

Join Discord