Terminal emulation and rendering for Unity

Coming soon to the Unity Asset Store

Put a working computer screen on any mesh or canvas. It looks like a real monitor, down to the scanlines and the cracked glass, and you write to it from C#. You can even run a full VT100 and xterm terminal on it.

DIG THIS BASSLINE? CHECK OUT GRINDSUB!

01 · Screens that look real

Three steps turn a mesh in your scene into a monitor. The same steps work on a uGUI canvas.

01
Add a session

GameObject, Terminal, Session. Turn on Start Demo Shell to see it working.

02
Add a screen

Terminal Screen (3D) on any mesh, or Terminal Screen (UI) in a canvas. Point it at the session.

03
Pick a look

Give the session a theme and the screen a screen type, from the presets or your own.

The same picture on the Flat screen type
Flat
The same picture on the Green CRT screen type
Green CRT
The same picture on the Amber CRT screen type
Amber CRT
The same picture on the Color CRT screen type
Color CRT

During play.

Power off and on screen.PowerCycle();
Lost vertical hold screen.LoseVerticalHold(0.6f);
A worn tape screen.Signal = SignalCondition.Vhs(1f);
A scrambled channel screen.Signal = SignalCondition.Scrambled(0.6f);
A glitch burst screen.Glitch(0.3f, 0.8f);
A cue with a wobble screen.Play(cue);
A cracked panel
A cracked panel screen.DamageFromRay(ray, 0.9f);
Three impacts
Three impacts screen.Damage(impact);

What you get

Display effects
Scanlines, an aperture grille or slot mask, barrel curvature, vignette, glow, halation, chromatic aberration, misconvergence, phosphor persistence, flicker, a rolling band, black level, backlight bleed, burn-in, tint, and brightness, set per screen. Every setting applies during play.
Presets
Flat, Green CRT, Amber CRT, and Color CRT screen types, and Clean LCD, Green Phosphor, and Amber Phosphor themes.
Sharp text
The grid is drawn pixel exact and the effect is applied at display time, so the text underneath stays sharp.
Power
A screen switches off and on with its look: a tube collapses to a line and a dot and warms back up, and a flat panel cuts.
The signal
A picture that rolls and locks again, interference from a flicker to a broken signal, a scrambled channel, a worn tape with tracking and dropouts, and a corrupted digital stream. Set a condition and it holds, or play it as a cue with an envelope and a wobble over whatever is set.
Panel damage
Crack an LCD where something hits it, by cell, ray, or world point: long cracks, with stuck lines and dead regions that change across them. The cracks stay until repaired, and a saved impact redraws the same ones.
Lights the room
Terminal Screen Light drives any Light from the picture on the screen: its color and its brightness, every frame. Green text casts green light, and a screen that switches off takes the light with it.
Behind glass
The Terminal Screen sub graph puts the display in a Shader Graph material of your own, with glass depth, brightness, glass smoothness, and the panel's viewing angle. A CRT screen type shows through the glass, and cracks come out as normal and smoothness, so the glass catches the light along them.
Terminal Monitor
A modeled monitor prefab with its own session, in the Demo sample. Drag it into any scene, and drag its frame to turn it.
Edit-time preview
Outside Play mode, the Scene and Game views show each screen with its theme and screen type, and follow your edits.
Many screens
A CRT on a desk and a flat panel in a canvas can show the same session, each with its own screen type.
Render pipelines
URP and HDRP, with no setting to change.
Themes and screen types in the manual -> Screen behaviors in the manual ->
02 · Content from panels and controls

Build what the screen shows as a tree of elements in C#, with no escape sequences to learn. This is a whole interface, with a log, a gauge, a text input, and working buttons:

On a Color CRT The engine room interface on a color CRT screen type
The code
var log = new LogView();
var fuel = new ProgressBar { Value = 0.4f };
var ui = new TerminalUI();

ui.Root = new Dock
{
    { Edge.Top, new Label("ENGINE ROOM") { Align = Align.Center } },
    { Edge.Bottom, new TextInput { OnSubmit = text => log.Add("> " + text) } },
    { Edge.Left, new Border("Controls") { Width = 22, Child = new Stack
        {
            new Label("Fuel"), fuel,
            new CheckBox("Pumps") { OnChanged = on => log.Add(on ? "Pumps on." : "Pumps off.") },
            new Button("Close", ui.Close),
        } } },
    new Border("Log") { Child = log },
};

session.RunSurface(new UISurfaceProgram(ui));

Headlines draw large, in any FIGlet font:

On an Amber CRT ALERT in large FIGlet lettering on an amber CRT screen type
The code
[SerializeField] FigletFontAsset titleFont;

var title = new BigText { Text = "ALERT", Font = titleFont.Font, Align = Align.Center };

What you get

Layout
Dock, Stack, Grid, Border, and Spacer, sized in whole cells.
Controls
Label, Button, CheckBox, TextInput, ListView, LogView, and ProgressBar.
Text that wraps
Labels and logs wrap at words or anywhere. Widths count cells, so wide characters and combining marks land where they should.
Focus and input
Tab and Shift+Tab move focus, a click focuses what it lands on, and lists and text inputs handle their own keys, paste, and the wheel.
Pointing in the scene
A scene screen maps the camera ray to a cell, following the curvature, so a player clicks a button on a monitor across the room. Supply a ray of your own for an XR controller or an in-game cursor.
Live textures
TextureView reserves room in the layout by name. Bind a camera feed or any other texture to that name on the session, and draw labels, brackets, or a reticle over it in characters.
Big lettering
BigText draws headlines in a FIGlet font. The Standard font is bundled, and a .flf file in the project imports as an asset.
Charts
Sparkline graphs a stream of values, and bars fill in eighths of a cell for smooth gauges. A ColorRamp colors a bar along its length, green through yellow to red.
Color
Mix two colors as stored, by light, or perceptually, and read a ColorRamp by position for a heat map or a fading trail.
Your own drawing
Paint gives you a region and a canvas with text, fill, and box calls, for a gauge or a waveform.
Theme colors
An interface starts from the session palette, so it follows the theme.
Showcases
Seven animated interfaces in the Demo sample to run and copy: a station dashboard, a radar, a spectrum analyzer, a star map, a dossier with marked-up photographs, a boot sequence, and falling code.
Printed lines
For a boot sequence or a log a player only reads, print lines from game code with session.Emulator.FeedText.
Interfaces in the manual ->
03 · A real terminal, because you can

Underneath is a VT100 checked against vttest, with the xterm additions programs rely on. One line points it at a MUD, a server of your own, or a program in-process, and the demo shell has a telnet command to try a host with.

The demo shell
darkeffekt:~$ telnet telehack.com
Connecting to telehack.com:23. Ctrl-] disconnects.
The code
session.SetConnection(new TelnetConnection("your.mud", 4000));
session.SetConnection(new TcpConnection("your.game.server", 4000));
session.SetConnection(new LocalProgramConnection(new DemoShell()));

What you get

Emulation
A VT100 that passes every VT100 screen of vttest, with the VT102 and xterm additions programs rely on: 256 colors and 24-bit truecolor, the alternate screen, scroll regions, DEC line drawing, double-width and double-height lines, UTF-8, wide characters, and combining marks.
Interaction
Mouse tracking in the X10 and SGR encodings, bracketed paste, scrollback, drag selection, and the clipboard.
Telnet
Option negotiation, window size reports on resize, and a terminal type of xterm-256color, for a MUD, a BBS, or a login service. Note: Telnet is unencrypted.
Raw TCP
A byte stream for a line-based service: a MUD on a plain port, or a server of your own.
In-process programs
Host a program that reads input bytes and writes escape sequences, as a remote host does: an in-game console, a text game, or a ported terminal program.
WebSocket
A byte stream over ws or wss on every platform, plus a connection for a command line program shared by ttyd. In a WebGL build, where TCP and telnet cannot run, this is how a session reaches a host.
Your own connection
One interface bridges a pty or a serial port. For an operating-system shell on desktop, start the process and bridge its standard streams.
Plain dotnet
The emulator core has no engine references. It builds and runs under plain dotnet, in a test project or on a server.
Connections in the manual ->
In the box
UNITY 6000.0 OR NEWER · URP · HDRP
SCREENS 3D MESH · UGUI CANVAS
CONNECTIONS TELNET · TCP · WEBSOCKET · TTYD · IN-PROCESS
PRESETS 3 THEMES · 4 SCREEN TYPES · 6 SIGNALS
FONTS JETBRAINS MONO · STANDARD FIGLET
SAMPLE DEMO SCENE · MONITOR PREFAB
DOCS MANUAL · SCRIPTING API
What to use when, in the manual ->
Availability
Coming soon to the Unity Asset Store

Hear when Terminal ships

One email when it reaches the Asset Store, then product updates and announcements, with a one-click unsubscribe in every email. See the privacy policy.

The live demo's rogue command plays Rogue 5.4.4 by Michael Toy, Ken Arnold, and Glenn Wichman, built with ncurses. The demo draws with JetBrains Mono, Noto Sans Mono CJK, and the Standard FIGlet font. Third-party licenses.