Build In-World UI with the Banter UI System

The Banter UI system creates 2D interfaces in VR. A BanterUIPanel is added to a GameObject, and its root contains labels, buttons, sliders, toggles, scroll views, and visual layout elements.

World-Space UI Structure

Create and position a panel GameObject, add BanterUIPanel, then append styled UI elements to the panel root.

  1. Create a GameObject at the intended physical position and rotation.
  2. Add BanterUIPanel with the required resolution and interaction feedback.
  3. Create controls, register their events, and append them to panel.root.

Create a World-Space Panel

const panelObject = new BS.GameObject({
  name: "ControlPanel",
  localPosition: new BS.Vector3(0, 1.4, 2)
});

const panel = panelObject.AddComponent(new BS.BanterUIPanel({
  resolution: new BS.Vector2(800, 600),
  screenSpace: false,
  enableHaptics: true,
  clickHaptic: new BS.Vector2(0.1, 0.05)
}));

The official component also supports pointer-enter and pointer-exit haptics, plus click, enter, and exit sounds.

screenSpace: false creates a world-space UI. Its physical placement comes from the GameObject's Transform.

Add a Label

const title = new BS.UILabel();
title.SetProperty(BS.PN.text, "Space Controls");
title.style.fontSize = "30px";
title.style.color = "#FFFFFF";
panel.root.AppendChild(title);

UI properties can be changed with SetProperty(), SetProperties(), or the named properties described in the official reference.

Add a Button

const button = new BS.UIButton();
button.SetProperty(BS.PN.text, "Start");
button.style.width = "200px";
button.style.height = "50px";
button.style.backgroundColor = "#4CAF50";
button.OnClick(() => console.log("Start clicked"));
panel.root.AppendChild(button);

The event must be registered on the control that should receive the interaction.

Add Sliders and Toggles

UISlider and UIToggle emit change events:

const volume = new BS.UISlider();
volume.style.width = "240px";
volume.OnChange((event) => {
  console.log(event.value);
});

const enabled = new BS.UIToggle();
enabled.OnChange((event) => {
  console.log(event.value);
});

panel.root.AppendChild(volume);
panel.root.AppendChild(enabled);

Use the current event payload from the official API when connecting a control to scene logic.

Build Layout Containers

UIVisualElement is a generic container. The Banter reference exposes flexbox-style properties such as:

  • flexDirection
  • justifyContent
  • alignItems
  • flexGrow
  • flexWrap
  • width and height constraints
  • margin and padding
  • borders and backgrounds
  • text styles
  • position and overflow
const row = new BS.UIVisualElement();
row.style.flexDirection = "row";
row.style.justifyContent = "space-between";
row.style.padding = "10px";
panel.root.AppendChild(row);

Append controls to the container instead of the root when they belong in the same layout group.

Add Scrolling

UIScrollView provides a scrollable container:

const list = new BS.UIScrollView();
list.style.width = "500px";
list.style.height = "300px";
list.style.overflow = "scroll";
panel.root.AppendChild(list);

Give the scroll view explicit dimensions so overflow has a defined area.

UI Hierarchy and Queries

All Banter UI controls inherit from UIElement. The base class provides:

  • AppendChild()
  • RemoveChild()
  • InsertBefore()
  • QuerySelector()
  • QuerySelectorAll()
  • property and style getters and setters
  • click, pointer, keyboard, focus, change, and wheel events

Each element exposes its parent, children, enabled state, and visible state.

Interaction Feedback

BanterUIPanel can provide haptic and audio feedback for clicks, pointer entry, and pointer exit. Keep feedback proportional to the interaction and test it with the controls at their final physical scale.

Common Questions

Why does my Banter control exist but not appear in the panel?

Append the control to panel.root or another UIElement that is already in the panel hierarchy, then check its visible state and layout dimensions.

Why is my scroll view not scrolling?

Give the scroll view a defined width and height, set its overflow behaviour, and make sure its child content is larger than the visible area.

Official References

Related Navigation