Learn about this Experimental feature, but you cannot publish a project that uses it.
Camera Modifiers
A Scene Graph camera is not a fixed set of properties. Every camera_component owns an ordered stack of camera modifiers, and each modifier is a small operation that takes the camera's current state, changes part of that state, and passes it on to the next modifier in the stack. The camera you see is the result of running the whole stack from bottom to top.
This means a camera type such as perspective_camera_component is really a starting point, and behaviors like orbiting a character or framing a target are modifiers layered on top.
The stack has some behaviors worth knowing before you use it:
The stack lives on the camera:
camera_componentimplements thehas_camera_modifierinterface, which exposes aCameraModifiersstack of typemodifier_stack(camera_state).Each entry has a position: Positions are
rationalvalues, and modifiers are evaluated in ascending position order. If two modifiers share a position, the most recently added one is evaluated last.Adding a modifier returns a handle:
AddModifierreturns acancelable. CallCancel()on it to take the modifier back out of the stack.The camera type itself is a modifier: When a camera component begins simulation it inserts its own implementation modifier at
CameraModifiers.FirstPosition. Anything you add at a higher position runs after it and layers on top.Modifiers are configured from Verse: Modifier properties are not exposed to the Details panel. Set them when you construct the modifier, or write to them later through the reference you kept.
Modifiers are evaluated on the client: The state that feeds the stack is replicated from the server, but the stack itself runs client-side so the camera stays responsive to input and frame rate.
The Camera State
Every modifier reads a camera_state and returns a camera_state. That state is what the renderer eventually consumes.
Only modifiers read or write camera_state. For reference, these are its properties:
| Property | Description |
|---|---|
| The location the camera renders from. This is separate from the transform of the camera's entity, so a modifier can offset or shake the view without moving anything in the world. |
| The rotation the camera renders with, again independent of the entity's transform. |
|
|
| How wide the camera projects in orthographic mode, in centimeters. |
| Physical camera body settings. Used by |
| Physical camera lens settings. Used by |
| How much of the physical body and lens settings to apply, from |
| Near clipping plane override. |
| Far clipping plane override. |
Because RenderLocation and RenderRotation are distinct from the entity transform, a modifier is free to move the view without desynchronizing gameplay. Collision pushback and potential camera shake both work this way.
Adding Modifiers in Verse
Modifiers are added to the stack from Verse, usually when the camera's entity begins simulation.
using { /Fortnite.com/SceneGraphCameras }
using { /Verse.org/SceneGraph }
using { /Verse.org/Simulation }
using { /Verse.org/SpatialMath }
# Turns the perspective camera on this entity into a third person orbit camera
# that swings back behind its target when the player stops steering it.
orbit_setup_component := class(component):
# The entity the camera orbits around.
Modifier properties are mutable and replicated, so you can retune a live camera by writing to the modifier you kept a reference to, instead of tearing the stack down and rebuilding it.
Built-in Modifiers
Fortnite ships a set of camera modifiers in the SceneGraphCameras module. They cover the camera behaviors most projects need, and they are the recommended starting point.
Fixed Angle
fort_fixed_angle_camera_modifier holds a constant angle on a target entity, which suits isometric, top-down, and over-the-shoulder framings.
It looks at TargetEntity from CameraDistanceCentimeters away, at the orientation given by RotationOffset, which defaults to looking down 45 degrees.
Set the following properties on this modifier:
CameraDistanceCentimeterssets how far back the camera sits, defaulting to1200.0.PositionOffsetCentimetersandRotationOffsetnudge the result without changing the target.ForwardDampingFactor,LateralDampingFactor, andVerticalDampingFactorsmooth motion per axis.0.0follows the target exactly.EnableCollision,CollisionSphereRadiusCentimeters, andCollisionSafePositionOffsetCentimeterscontrol camera-to-world collision avoidance.
Fixed Point
fort_fixed_point_camera_modifier keeps the camera where it is and rotates in place to keep one or more entities framed, which is the behavior you want for security cameras, spectator posts, and staged shots.
Set the following properties on this modifier:
TargetEntitiesis the list of entities to keep in frame.IdealFramingLocationScreenSpaceLeftandIdealFramingLocationScreenSpaceUpset where on screen the target should sit. Values are normalized, so0.5is the center.CanYawandCanPitchrestrict the correction to one axis. Turn offCanPitchfor a pan-only camera, orCanYawfor a tilt-only camera.The dead zone properties (
DeadZoneScreenSpace*) define the screen region where the target can move without the camera reacting. The soft zone properties (SoftZoneScreenSpace*) define the region inside which reframing happens at normal strength. Outside the soft zone, the camera switches to stronger damping to catch up.ReframeDampingFactorsets how aggressively the camera corrects, where 0.0 snaps instantly and higher values are smoother but lag more.LowReframeDampingFactoroptionally interpolates the damping as the target moves out toward the soft zone.TargetMovementAnticipationTimeSecondsframes where the target will be that many seconds from now based on its velocity, which stops the camera trailing behind fast movers.ReengageTimeSecondsramps the reframing back up after the target leaves the dead zone, instead of correcting the instant it crosses the boundary.SnapToIdealFramingOnEnabledecides whether the first frame starts already framed or eases in.RotationOffsetapplies a final adjustment to the camera's orientation.
Orbit
fort_orbit_camera_modifier implements a third-person orbit camera on a boom arm around a target entity.
Set the following properties on this modifier:
TargetEntityis the entity the camera orbits.CameraDistanceCentimetersandCameraHeightCentimetersplace the pivot and the arm length, defaulting to180.0and40.0.BoomArmOffsetCentimetersoffsets the arm relative to the entity, andBoomArmMaxForwardInterpolationFactorandBoomArmMaxBackwardInterpolationFactorlimit how far the arm extends and retracts.ForwardDampingFactor,LateralDampingFactor, andVerticalDampingFactorsmooth motion per axis.EnableCollision,CollisionSphereRadiusCentimeters, andCollisionSafePositionOffsetCentimeterscontrol collision avoidance.PositionOffsetCentimetersandRotationOffsetapply a final adjustment after the boom arm.
How the Modifier System Works
Scene Graph camera modifiers are a Verse-facing layer over the Gameplay Cameras system, and understanding the mapping helps when you are debugging.
Each stack becomes a camera rig. When a modifier stack changes, the camera component rebuilds a transient camera rig whose root is an array node with one child node per modifier, in stack order. A target ray cast node is appended at the end to establish the camera's target distance, which the orbit blend uses.
Rebuilds are deferred. Adding or cancelling a modifier marks the camera's context dirty, and the rig is rebuilt on the next director evaluation rather than immediately.
Built-in modifiers wrap native camera rigs. The modifiers in
SceneGraphCameraseach reference a prebuilt camera rig asset, for example/FortSceneGraphCameras/CameraRigs/fort_orbit. Every frame, the node that wraps the modifier copies the modifier's current Verse property values into the rig's parameters, which is why editing a live modifier takes effect immediately.Modifier properties are replicated. Modifier properties are replicated to clients, and the client evaluates the stack. This is what lets a camera respond to local input at full frame rate while the server remains authoritative over what the camera is doing.
Writing a modifier's Evaluate function yourself in Verse is not available yet. Running creator Verse on the client requires <predicts> support that is still in development, so build camera behavior by working with the built-in modifiers for now.