Skip to Content
GuideGetting Started

Getting Started

This guide walks through everything from creating a new Unity project to rendering your first Fram3 element on screen.

See it in action first. The Fram3 repository  includes a Storybook that demonstrates every element and feature of the framework. Open the project in Unity and run the Storybook scene to browse live, interactive examples before writing any code yourself.

Requirements

  • Unity 6000.3 or later
  • UIToolkit (included with Unity — no extra installation needed)

Step 1 — Create a Unity project

Open Unity Hub and create a new project. Any template works; 3D (URP) or 2D are fine starting points. Fram3 only needs UIToolkit, which ships with Unity 6 by default.

Step 2 — Install the package

Open Packages/manifest.json in your project root (any text editor works) and add the Fram3 entry under dependencies:

{ "dependencies": { "com.fram3.ui": "https://github.com/gabaudette/fram3.git?path=Packages/com.fram3.ui" } }

Save the file. Unity will detect the change, fetch the package from GitHub, and compile it. Wait for the progress bar in the bottom-right corner to finish.

Alternatively, use the Package Manager window: open Window > Package Manager, click the + button, choose Add package from git URL, and paste:

https://github.com/gabaudette/fram3.git?path=Packages/com.fram3.ui

Step 3 — Create a Panel Settings asset

UIToolkit requires a Panel Settings asset to control rendering resolution and scaling.

  1. In the Project window, right-click inside Assets/ and choose Create > UI Toolkit > Panel Settings.
  2. Name it PanelSettings (or any name you prefer).
  3. Leave the defaults as-is for now. You can tune scale mode and reference resolution later.

Step 4 — Add a UIDocument to a scene GameObject

  1. Open or create a scene.
  2. In the Hierarchy window, right-click and choose Create Empty. Name it UI.
  3. With the UI GameObject selected, click Add Component in the Inspector and add UI Document (search for “UI Document”).
  4. In the UI Document component, assign the Panel Settings asset you created in the previous step to the Panel Settings field.
  5. Leave the Source Asset field empty — Fram3 manages the visual tree entirely in code.

Step 5 — Write your app root

Create a new C# script in Assets/ called MyApp.cs. This is the single entry point for your UI. Subclass AppRoot and override CreateRoot to return the root element of your interface:

using Fram3.UI.Core; using Fram3.UI.Elements.Content; using Fram3.UI.Elements.Layout; using Fram3.UI.Rendering; public sealed class MyApp : AppRoot { protected override Element CreateRoot() => new CounterElement(); }

AppRoot is a MonoBehaviour that handles mounting, ticking, and disposing the renderer automatically. You only need to supply the root element.

Step 6 — Write your first element

Create a new C# script in Assets/ called CounterElement.cs:

using Fram3.UI.Core; using Fram3.UI.Elements.Content; using Fram3.UI.Elements.Layout; public sealed class CounterElement : StatefulElement { public override State CreateState() => new CounterState(); private sealed class CounterState : State<CounterElement> { private int _count; public override Element Build(BuildContext context) { return new Column { Children = new Element[] { new Text($"Count: {_count}"), new Button( label: "Increment", onPressed: () => SetState(() => _count++)), } }; } } }

StatefulElement is the base for elements that own mutable state. State holds the state and implements Build, which returns an immutable description of the UI. Calling SetState schedules a rebuild — only the elements that changed are patched in the UIToolkit tree.

Step 7 — Attach MyApp to the scene

  1. Select the UI GameObject in the Hierarchy.
  2. Click Add Component and search for MyApp.
  3. The component appears in the Inspector. AppRoot requires a UIDocument on the same GameObject, which you added in Step 4.

Hit Play. You should see a column with the text “Count: 0” and an “Increment” button. Clicking the button increments the count.

What just happened

  • AppRoot detected the UIDocument on the same GameObject, applied full-screen sizing to the root visual element, created a Renderer, and called CreateRoot() to mount the tree.
  • The renderer’s tick and dispose calls are wired to Update and OnDestroy automatically — no boilerplate required.
  • Mount set the root element. From that point on, every SetState call triggers a diff between the new element tree and the previous one, and only the changed nodes are updated in the underlying visual tree.
  • No UXML, no USS files, no code generation — the entire UI is described in C#.

Next steps

Last updated on