Camera
The Camera API lets you inspect the scene’s main camera and create additional cameras. A custom camera renders into a texture that can be displayed through UI or ImGui.
This entire API is client-only. In a Reflex module’s server.lua, the global Cameras object is nil.
How the game processes a camera
Section titled “How the game processes a camera”Cameras.Main wraps the game client’s real active camera. Setters immediately change its component, but character and other camera controllers may write their own state on the next frame.
CreateCamera() registers a separate client camera and creates a render texture for it. While active, the renderer updates OutputTexture; SetActive(false) stops new frames, while RemoveCamera() removes the created resource. None of these calls adds the texture to the HUD by itself.
Key points
Section titled “Key points”Cameras.Mainreturns the main camera and is read-only.Cameras:CreateCamera()creates a custom camera.IsMainCameraandOutputTextureare read-only properties.SetActive(false)stops updatingOutputTextureand preserves its last frame.- A custom camera does not replace the main view automatically. You must display its
OutputTextureyourself.
Where the result appears
Section titled “Where the result appears”| Action | What changes |
|---|---|
Modifying Cameras.Main |
Immediately changes the main game view. The game may overwrite the values on the next frame. |
| Creating a custom camera | Does not add anything to the screen by itself. Its image is available only through OutputTexture. |
SetActive(false) |
Freezes texture updates but does not hide an image that is already being displayed. |
WorldToViewportPoint() |
Only calculates a point’s screen position and does not draw anything. |
To show a custom camera, pass its OutputTexture to ImGui or a UI element. Texture resolution and on-screen size are independent.
Complete example
Section titled “Complete example”This example creates a 320 × 180 preview in the top-left corner. The custom camera follows the main camera from a position two metres above it.
local PreviewCamera = Cameras:CreateCamera()
if PreviewCamera == nil then print("[Camera example] Camera limit reached")else PreviewCamera:SetRenderSize(320, 180) PreviewCamera.Aspect = 320 / 180 PreviewCamera.Fov = 60 PreviewCamera:SetActive(true)
Scheduler:OnFrame(function() local mainCamera = Cameras.Main PreviewCamera.Position = mainCamera.Position + Vector3.new(0, 2, 0) PreviewCamera.Rotation = mainCamera.Rotation
local texture = PreviewCamera.OutputTexture if texture ~= nil then ImGui:DrawTexture(texture, Rect.new(20, 20, 320, 180)) end end)endImGui uses immediate-mode rendering, so DrawTexture is called every frame. The camera itself is created only once.
Camera
Section titled “Camera”Represents either the main camera or a custom camera. Camera objects are not constructed directly; use Cameras.Main or Cameras:CreateCamera().
Properties
Section titled “Properties”| Property | Type | Access | Description |
|---|---|---|---|
Aspect |
number |
get/set |
Image width divided by image height. |
FarClipPlane |
number |
get/set |
Far clipping plane in metres. |
Fov |
number |
get/set |
Vertical field of view in degrees. |
IsMainCamera |
bool |
get |
true only for the scene’s main camera. |
IsOrthographic |
bool |
get/set |
Whether orthographic projection is enabled. |
NearClipPlane |
number |
get/set |
Near clipping plane in metres. |
OrthographicSize |
number |
get/set |
Orthographic camera size. Used when IsOrthographic = true. |
OutputTexture |
Texture | nil |
get |
The custom camera’s output texture. Returns nil for the main camera. |
Position |
Vector3 |
get/set |
Camera position in world space. |
Rotation |
Quaternion |
get/set |
Camera rotation in world space. |
SetActive
Section titled “SetActive”camera:SetActive(value: bool)Starts or stops rendering a custom camera.
| Parameter | Type | Description |
|---|---|---|
value |
bool |
true updates the image; false stops updates. |
When set to false, the camera object and its OutputTexture remain available, and the texture keeps the last rendered frame. Calling the method with true resumes rendering.
SetRenderSize
Section titled “SetRenderSize”camera:SetRenderSize(width: int, height: int)Sets the custom camera’s OutputTexture size in pixels.
| Parameter | Type | Description |
|---|---|---|
width |
int |
Texture width. |
height |
int |
Texture height. |
After camera:SetRenderSize(320, 180), camera.OutputTexture.width and camera.OutputTexture.height return 320 and 180.
SetRenderSize does not update Aspect automatically. These values are usually set together:
camera:SetRenderSize(320, 180)camera.Aspect = 320 / 180WorldToViewportPoint
Section titled “WorldToViewportPoint”camera:WorldToViewportPoint(worldPosition: Vector3): Vector3Converts a world-space position to viewport coordinates:
(0, 0)is the bottom-left corner;(1, 1)is the top-right corner;zis the distance from the camera in metres;- a negative
zmeans that the point is behind the camera.
For a camera at the world origin with Fov = 90, Aspect = 1, and zero rotation, the method returns:
| World position | Result |
|---|---|
(0, 0, 10) |
(0.5, 0.5, 10) — screen centre |
(10, 0, 10) |
(1, 0.5, 10) — right edge |
(0, 10, 10) |
(0.5, 1, 10) — top edge |
(0, 0, -10) |
(0.5, 0.5, -10) — behind the camera |
Cameras
Section titled “Cameras”The global client-side API for accessing and creating cameras.
local mainCamera = Cameras.MainReturns the scene’s main camera. The Main property itself is read-only.
CreateCamera
Section titled “CreateCamera”local camera = Cameras:CreateCamera()Creates and returns a custom camera. Check the returned value for nil before using it.
RemoveCamera
Section titled “RemoveCamera”Cameras:RemoveCamera(camera)Removes a previously created custom camera. Do not use a stored reference after removing the camera.
camera:SetActive(false)Cameras:RemoveCamera(camera)camera = nilCommon mistakes
Section titled “Common mistakes”Writing to read-only properties
Section titled “Writing to read-only properties”The following operations raise a Lua access error:
Cameras.Main = cameracamera.IsMainCamera = truecamera.OutputTexture = textureExpecting the main view to switch automatically
Section titled “Expecting the main view to switch automatically”camera:SetActive(true) starts the custom camera’s renderer but does not replace the main camera’s image. Display camera.OutputTexture through a UI element or ImGui:DrawTexture().
Using a point behind the camera
Section titled “Using a point behind the camera”Checking only x and y is not enough. Before drawing a marker, make sure the value returned by WorldToViewportPoint() has z > 0.