githubEdit

Websocket (Pro)

High-performance WebSocket interface for bidirectional signal exchange (Pro)

circle-info

This feature was added in realvirtual 6.3 (Professional).

circle-info

This interface requires the REALVIRTUAL_JSON compiler define. See Newtonsoft JSON for setup instructions.

Overview

The WebSocket Realtime Interface provides high-performance, bidirectional signal exchange over WebSocket connections. It operates as both server and client, enabling connectivity between two Unity instances, external applications, PLCs, or any system that supports WebSocket communication.

Built on the FastInterface framework, it offers thread-safe background communication, automatic reconnection, change detection, and low-latency signal transport.

Key capabilities:

  • Server and Client mode in a single component

  • Flat JSON wire protocol (v2) for easy integration from any language

  • Signal import from remote side with automatic direction inversion

  • SSL/TLS support (wss://) for secure connections through reverse proxies

  • Pattern-based signal direction detection for external systems without PLC-style type prefixes

  • Subscribe filtering so clients only receive the signals they need

Setup

Adding the Interface

  1. Drag the WebsocketRealtimeInterface prefab into your scene, or add the component to an existing GameObject

  2. The interface appears as a child of your realvirtual root object

  3. Create PLC signal objects (PLCInputBool, PLCOutputFloat, etc.) as children of the interface

WebSocket Realtime Interface Inspector

Server Mode

Set Is Server to true (in the Connection Settings foldout). The server listens on the configured address and port and broadcasts signal data to all connected clients.

  • Address: IP to bind to (127.0.0.1 for localhost, 0.0.0.0 for all interfaces)

  • Port: TCP port (default: 1234)

Client Mode

Set Is Server to false. The client connects to a remote WebSocket server.

  • Address: IP address of the server

  • Port: TCP port of the server

  • Use SSL: Enable for wss:// connections (e.g. through a reverse proxy)

  • Path: Optional URL path (e.g. /my-bridge/ws for reverse proxy routing)

  • Client Name: Identification sent during handshake

Signal Import

Client Mode Import (Edit Mode)

In client mode, you can import signals from the remote server without manually creating them:

  1. Make sure the remote server is running

  2. Click Import Signals in the Inspector (works in edit mode — no play mode required)

  3. The interface connects, requests the signal catalog, creates local mirror signals with inverted directions, and disconnects

You can also use Test Connection to verify connectivity without importing.

Server Mode Import (Play Mode)

In server mode, you can import signals from connected clients during play mode:

  1. Start the simulation so the server is running and clients are connected

  2. Click Import Signals from Clients in the Inspector

  3. The server broadcasts an import request to all connected clients and creates local mirror signals with inverted directions

This is useful for discovering which signals a remote client provides without manually defining them.

Properties

Configuration

Property
Description

Update Cycle Ms

Communication loop interval in milliseconds (default: 10)

Only Transmit Changed Inputs

Only send signals whose values changed since last cycle

Auto Reconnect

Automatically reconnect on connection loss

Reconnect Interval Seconds

Seconds between reconnection attempts

Max Reconnect Attempts

Maximum number of reconnection attempts before giving up (-1 = unlimited)

Debug Mode

Enable detailed logging for troubleshooting

Connection Settings

Property
Description

Is Server

true = WebSocket server, false = WebSocket client

Address

IP address to bind (server) or connect to (client)

Port

TCP port for communication (default: 1234)

Use SSL

(Client only) Use wss:// for encrypted connections

Path

(Client only) Optional URL path appended after host:port

Client Name

(Client only) Name sent during init handshake

Connect On Play

Automatically connect when entering play mode

Status

Property
Description

Connected Clients

(Server only) Number of currently connected clients

Signal Import

Property
Description

Default Signal Direction

Direction for imported signals when no pattern matches (Input or Output)

Use Pattern Matching

Enable name-based direction detection

Input Patterns

Name substrings that identify signals Unity writes (e.g. "Unity")

Output Patterns

Name substrings that identify signals the PLC writes

Use Cases

  • Unity-to-Unity distributed simulation with signal mirroring

  • External application integration (web dashboards, custom HMIs, test frameworks)

  • PLC bridge connections (e.g. via a bridge application running on ctrlX CORE or other edge devices)

  • WebGL builds where TCP-based protocols are not available


Wire Protocol v2 Reference

The WebSocket Realtime Interface uses a flat JSON protocol. All messages are UTF-8 encoded JSON objects sent as WebSocket text frames. There is no double-encoding - all fields are native JSON types.

Message Envelope

Every message has a type field that determines its purpose:

Message Types

init - Client Identification

Sent by the client immediately after the WebSocket connection is established.

Field
Type
Description

type

string

Always "init"

version

int

Protocol version (2)

name

string

Client identification name

data - Cyclic Signal Exchange

Sent cyclically in both directions. Contains signal names and their current values.

Field
Type
Description

type

string

Always "data"

signals

object

Map of signal name to current value. Values are native JSON types: true/false for bool, numbers for int/float, strings for text.

import_request - Signal Discovery Request

Sent from one side to request the full signal catalog from the other side.

import_answer - Signal Catalog Response

Response to import_request. Contains all signal names, their current values, and their PLC type strings.

Field
Type
Description

signals

object

Signal name to current value

signalTypes

object

Signal name to type string. Recognized types: PLCInputBool, PLCOutputBool, PLCInputInt, PLCOutputInt, PLCInputFloat, PLCOutputFloat, PLCInputText, PLCOutputText. Neutral types without prefix (e.g. Bool, Float) are also accepted.

Direction inversion on import: When the receiving side imports signals, the direction is inverted:

  • Remote PLCInputBool (remote reads from PLC) becomes local PLCOutputBool (local writes to Unity)

  • Remote PLCOutputBool (remote writes from PLC) becomes local PLCInputBool (local reads from Unity)

subscribe - Filter Server Output

Sent by the client to tell the server which signals it wants to receive. The server then only sends matching signals in data messages. If no subscribe message is sent, the server sends all signals.

snapshot - Immediate Full State

Sent by the server after receiving a subscribe message. Contains the current values of all subscribed signals.

config_get - Read Server Configuration

Sent by the client to request the current configuration from the server (e.g. a bridge application).

config_answer - Configuration Response

Sent by the server in response to config_get. Contains the current configuration as a key-value map.

Field
Type
Description

config

object

Application-specific key-value configuration map. The structure depends on the server implementation.

config_set - Write Server Configuration

Sent by the client to update configuration values on the server. The server should persist and apply the new configuration.

config_result - Configuration Update Result

Sent by the server in response to config_set. Reports whether the configuration was applied successfully.

Field
Type
Description

success

boolean

true if the configuration was applied, false on error

message

string

Human-readable result message

circle-info

The config messages are optional and application-specific. They are used by the ctrlX bridge to remotely configure publish intervals, logging levels, and Data Layer browse paths. If you implement your own server, you can define any key-value structure for the config field or ignore these messages entirely.

Signal Value Types

realvirtual Type
JSON Type
Example

PLCInputBool / PLCOutputBool

boolean

true, false

PLCInputInt / PLCOutputInt

integer

42, -1, 0

PLCInputFloat / PLCOutputFloat

number

3.14, 0.0, -100.5

PLCInputText / PLCOutputText

string

"Running", ""


Implementing the Other Side

This section describes how to build your own WebSocket application that communicates with the realvirtual WebSocket Realtime Interface. You can use any programming language that supports WebSocket connections.

Connection Sequence

When connecting to a realvirtual server:

When running your own server that realvirtual connects to as client:

Example: Python Client

A minimal Python client that connects to a realvirtual server, imports signals, and exchanges data:

Example: Python Server

A server that realvirtual connects to as a client. This is useful when your application is the "host" and realvirtual is a connected client:

Example: C# Client (.NET)

For .NET applications (e.g. a bridge application on a PLC or edge device):

Example: JavaScript / TypeScript (Browser or Node.js)

Direction Mapping Guide

When implementing the other side, understanding signal direction is critical:

Your application sends...
realvirtual creates...
Meaning

signalTypes: {"Speed": "PLCOutputFloat"}

Local PLCInputFloat named "Speed"

Your app writes Speed, Unity reads it

signalTypes: {"Enable": "PLCInputBool"}

Local PLCOutputBool named "Enable"

Your app reads Enable, Unity writes it

signalTypes: {"Value": "Float"}

Direction from pattern matching or default

Neutral type - no direction prefix

Rule of thumb: If your application writes a value, declare it as PLCOutput. If your application reads a value from Unity, declare it as PLCInput. realvirtual inverts the direction on import.

Tips for Implementers

  • JSON only - All messages are JSON text frames. Binary frames are not used.

  • No heartbeat required - The cyclic data messages serve as implicit heartbeat. If you stop sending data, the connection remains open.

  • Partial updates - data messages do not need to contain all signals. You can send only the signals that changed.

  • Type coercion - realvirtual will attempt to convert JSON number types. Sending 1 for a float signal or 1.0 for an int signal works.

  • Signal names - Use consistent names between both sides. Names are case-sensitive and matched exactly.

  • SSL/TLS - For production deployments through reverse proxies (nginx, traefik), configure useSSL=true and set the path to match your proxy route.

Troubleshooting

Interface does not connect:

  • Check that the server is running and reachable on the configured address and port

  • For client mode, verify the address, port, SSL, and path settings

  • Use the Test Connection button to verify connectivity

  • Enable Debug Mode for detailed logging

Signals not updating:

  • Ensure signals are child GameObjects of the interface

  • Check signal directions (Input = Unity writes, Output = Unity reads)

  • Verify that signal names match exactly between both sides

  • Check the data messages being sent contain the expected signal names

Import creates wrong directions:

  • Review your signalTypes in the import_answer - PLCInput and PLCOutput are inverted on import

  • For neutral types, configure Input Patterns and Output Patterns or set the Default Signal Direction

See Also

Last updated