rojo/.cursor/rules/roblox/ui/viewport-frames.md
2026-02-02 12:08:47 -06:00

7.2 KiB

title description
Viewport frames ViewportFrames use a camera to render 3D objects into a 2D viewport.

A Class.ViewportFrame uses a camera to render 3D objects into a 2D viewport. Ideal use cases include:

  • A minimap of your experience directly in the corner of a user's screen.
  • 3D models of items in an inventory menu.
  • Rotating objects that a character has equipped.

Viewport configurations

3D objects that users view through a Class.ViewportFrame can either move with their camera, remain static, or rotate within the Class.ViewportFrame. This object can also include a Class.Sky child as a cubemap for reflections.

If you want a 3D object to move with the camera:

  1. Position your camera view within the experience so that the object you want to see within the frame is visible.

  2. Add a new Class.ViewportFrame to the screen and then make sure it's selected in the Explorer.

  3. In the Properties window, assign the Class.ViewportFrame.CurrentCamera|CurrentCamera property to the camera:

    1. Select the Class.ViewportFrame.CurrentCamera|CurrentCamera property. Your cursor changes.
    2. In the Explorer window, click on the top-level Class.Camera object.
  4. Parent the desired 3D object to the new Class.ViewportFrame. Note that if you still want to see the object within your experience, you must duplicate it in the Class.Workspace and then parent the duplicate object to the Class.ViewportFrame.

When you move your camera, the object will also move within the Class.ViewportFrame.

When you want to update the view of your `Class.ViewportFrame`, be sure to update the camera, **not** the objects within the view.

If you want the 3D object to remain static:

  1. Position your camera view within the experience so that the object you want to see is in the exact position you want to see it within the frame.

  2. In the Explorer window, duplicate the top-level Class.Camera object, then rename it to an identifiable name like ViewportCam.

  3. Add a new Class.ViewportFrame to the screen and then make sure it's selected in the Explorer.

  4. In the Properties window, assign the frame's Class.ViewportFrame.CurrentCamera|CurrentCamera property to the duplicated camera:

    1. Select the Class.ViewportFrame.CurrentCamera|CurrentCamera property. Your cursor changes.
    2. In the Explorer window, click on the duplicated camera object.
  5. Parent the desired 3D object to the new Class.ViewportFrame. Note that if you still want to see the object within your experience, you must duplicate it in the Class.Workspace and then parent the duplicate object to the Class.ViewportFrame.

If you want a 3D object such as a Class.BasePart to rotate on its own within the frame:

  1. Add a new Class.ViewportFrame to the screen.

  2. In the Explorer window, drag the desired Class.BasePart into the new Class.ViewportFrame.

  3. Insert a new Class.LocalScript into the Class.ViewportFrame and paste in the following code.

    local RunService = game:GetService("RunService")
    
    local viewportFrame = script.Parent
    
    -- Parameters to experiment with
    local cameraDistance = 10
    local cameraFieldOfView = 50
    local objectPitchAngle = 40
    local objectRotationSpeed = 50
    
    -- Viewport camera initialization
    local viewportCamera = Instance.new("Camera")
    viewportCamera.FieldOfView = cameraFieldOfView
    viewportFrame.CurrentCamera = viewportCamera
    viewportCamera.Parent = viewportFrame
    
    -- Viewport object initialization
    local object = viewportFrame:FindFirstChildWhichIsA("BasePart")
    if object then
    	object.CFrame = CFrame.new(0, 0, 0) * CFrame.Angles(math.rad(objectPitchAngle), 0, 0)
    
    	-- Update loop
    	local t = 0
    	RunService.PostSimulation:Connect(function(delta)
    		t += delta
    		viewportCamera.CFrame = CFrame.Angles(0, math.rad(t * objectRotationSpeed), 0) * CFrame.new(0, 0, cameraDistance)
    	end)
    else
    	warn("3D object not found as child of viewport frame")
    end
    

Class.ViewportFrame|ViewportFrames can use a Class.Sky child as a cubemap for reflections, in which case only the Class.Sky object's six Skybox[…] properties are used. Assuming these properties are valid, lighting inside the Class.ViewportFrame acts similarly to when Class.Lighting.EnvironmentSpecularScale and Class.Lighting.EnvironmentDiffuseScale are both set to 1.

To implement skybox cubemap reflections:

  1. Insert a Class.Sky object as a direct child of the Class.ViewportFrame.
  2. Set the Class.Sky object's six texture properties (Class.Sky.SkyboxBk|SkyboxBk, Class.Sky.SkyboxDn|SkyboxDn, Class.Sky.SkyboxFt|SkyboxFt, Class.Sky.SkyboxLf|SkyboxLf, Class.Sky.SkyboxRt|SkyboxRt, Class.Sky.SkyboxUp|SkyboxUp).
  3. For Class.Part|Parts that should appear within the frame, set their Class.BasePart.Reflectance|Reflectance property greater than 0, or use a reflectant material like Enum.Material.Glass|Glass or Enum.Material.Foil|Foil. For Class.MeshPart|MeshParts that should appear within the frame, apply a Class.SurfaceAppearance with a properly-configured Class.SurfaceAppearance.MetalnessMap|MetalnessMap.

Lighting and appearance

Lighting within a Class.ViewportFrame is controlled through three properties:

Property Description
`Class.ViewportFrame.Ambient|Ambient` Determines the overall lighting hue applied to the area within the viewport frame. Defaults to `Datatype.Color3.fromRGB(200, 200, 200)` (ghost grey).
`Class.ViewportFrame.LightDirection|LightDirection` A `Datatype.Vector3` representing the direction of the light source from position `(0, 0, 0)`. Defaults to `(-1, -1, -1)`.
`Class.ViewportFrame.LightColor|LightColor` Color of the directional light. Defaults to `Datatype.Color3.fromRGB(140, 140, 140)` (silver).

Additionally, you can adjust the overall rendered appearance of the viewport throuugh the following properties:

Property Description
`Class.ViewportFrame.ImageColor3|ImageColor3` Changes the image color/tint without modification of the rendered object. The default colorization value is `Datatype.Color3.new(1, 1, 1)` (white) at which no color modification occurs.
`Class.ViewportFrame.ImageTransparency|ImageTransparency` Changes the image transparency without modification of the rendered object. A value of `0` (default) is completely opaque and a value of `1` is completely transparent (invisible).