OrbitView (luna:OrbitView) is a RenderElement subclass that turns a 3D render into a turntable viewer: drag to rotate, flick for inertia, and an idle auto-orbit that resumes after release. It orbits the slot camera around the content on a fixed pivot; the content itself is never rotated, so live content (animated characters, particles, physics) keeps playing untouched.

The element owns the whole viewer presentation through UXML attributes, so the code side is a plain Play(prefab) with no settings object.

Quick Start

xml
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:luna="CupkekGames.Luna"> <luna:OrbitView name="WeaponView" render-width="768" render-height="480" frame-padding="1.35" frame-reference-extent="0.5" initial-yaw="30" initial-pitch="12" idle-orbit-speed="16" idle-resume-delay="1.5" pitch-min="-15" pitch-max="45" style="width: 100%; flex-grow: 1;" /> </ui:UXML>
csharp
OrbitView view = root.Q<OrbitView>("WeaponView"); view.Play(weaponPrefab); // element bakes framing, AA and orbit into the settings view.Play(otherWeaponPrefab); // swap: continues from the current orbit angle view.SetOrbit(yaw: 90f, pitch: 0f); // explicit jump, kills inertia

Scene setup is the same as the rest of UI Render (a UIRenderManager, a LunaUIManager, and a dedicated layer); see the UI Render Quick Start.

Viewer behavior

  • Drag rotates with the Sketchfab feel: the content appears to follow the pointer, so the camera orbits opposite the drag. Dragging up raises the camera. Pitch is clamped to pitch-min..pitch-max.
  • Release with velocity keeps spinning; the flick decays exponentially at inertia-damping.
  • Idle resumes the auto-orbit at idle-orbit-speed degrees per second once idle-resume-delay seconds pass without input. Set the speed to 0 to disable.
  • First play snaps to initial-yaw / initial-pitch. Every re-play, item swaps included, continues seamlessly from wherever the orbit currently is: the element bakes its current angles into the camera rotation before the slot activates, so there is no first-frame snap.
  • SetOrbit(yaw, pitch) jumps to an explicit angle and kills inertia. Calling it right after Play overrides the initial-angle snap.

Current angles are readable via the Yaw and Pitch properties.

UXML Attributes

On top of the inherited render-width / render-height:

AttributeDefaultDescription
drag-sensitivity0.4Degrees of rotation per pixel of drag.
idle-orbit-speed12Auto-orbit speed in degrees per second. 0 disables the idle orbit.
idle-resume-delay1.5Seconds after release before the idle orbit resumes.
inertia-damping4Exponential decay rate of flick inertia. Higher stops sooner.
pitch-min / pitch-max-15 / 45Camera pitch clamp in degrees.
initial-yaw / initial-pitch30 / 12Orbit angles for the first play.
auto-frametrueFrame the camera to the content bounds.
frame-padding1.2Auto-frame padding (1.0 = tight).
frame-reference-extent0Frame for this fixed extent instead of each content's own bounds; see below. 0 frames per content.
anti-aliasing4MSAA sample count for the slot's RenderTexture.
preserve-content-rotationtrueKeep the prefab's authored rotation instead of resetting it to identity.

These attributes are baked into the UIRenderSettings by the element itself (ResolveSettings is virtual on RenderElement), so a caller-supplied settings object passes through for everything else (resolution overrides, background color, HDR, and so on) while the viewer presentation stays element-owned.

True relative scale across items

By default auto-framing fits each content's own bounds, so a knife and a rifle both fill the frame at the same apparent size. Setting frame-reference-extent frames the camera for that fixed extent (in world units) instead: every item shown through the same element shares one frustum, so the knife reads smaller than the rifle. Pick the extent near the largest item's half-size, then tune frame-padding for breathing room.

Authored facing

Play normally spawns prefab copies at identity rotation. OrbitView defaults preserve-content-rotation to true, so the model keeps its authored facing and initial-yaw is relative to that. Disable it if your prefabs are authored at arbitrary rotations and you want a normalized start.

Demos

The Showcase sample's EsportLobby experience uses OrbitView twice:

  • ChampSelect mounts the selected operative's weapon into an OrbitView with frame-reference-extent="0.5", so switching operatives keeps the weapons at true relative scale.
  • BattlepassTab swaps reward items into an OrbitView on tile click, feeding per-item InitialYaw / InitialPitch from demo data before each Play; the swap continues from the current orbit, so browsing the track feels continuous.

See also

  • UI Render: the render pipeline this element sits on, with content modes, settings, handles, and pooling.
  • UI Render Settings: WithFrameReferenceExtent and the rest of the builder API.

Settings

Theme

Light

Contrast

Material

Dark

Dim

Material Dark

System

Sidebar(Light & Contrast only)

Light
Dark

Font Family

DM Sans

Wix

Inclusive Sans

AR One Sans

Direction

LTR
RTL