Camera

Camera extends Object, adding functions and properties to it.
Camera is not creatable, there's only one instance of it. It can only be accessed through its globally exposed variable.

A Camera is an object that can be placed in the scene to render all or select elements based on their layers.

The global instance Camera corresponds to the default main camera that renders to fullscreen. Additional cameras are rendered on top, according to their view order. Their output can optionally be displayed inside a custom screen rectangle, called a target.

All camera modes listed on this page are implemented in Lua, it's totally possible to implement custom ones.

Code examples of Camera's various fields can be found in the following worlds,
- Camera Projection Modes
- Radar FX Example
- Multi Camera UI Example
- Minimap Example

Functions

Impact CastRay ( Shape filterIn )
Impact CastRay ( nil filterIn, Object filterOut )
Impact CastRay ( CollisionGroups filterIn, Object filterOut )
Impact CastRay ( Shape filterIn, Object filterOut )

Casts a ray and returns an Impact (can be nil).

The Impact contains information about the kind of thing that's been hit.

💡 Calls Ray.Cast under the hood. See Ray.Cast definition for more details about possible filters.

local impact = Camera:CastRay()
if impact.Block ~= nil then
  print("block hit:", impact.Block)
end
nil FitToScreen ( Shape target, table options optional )
nil FitToScreen ( Box target, table options optional )
nil FitToScreen ( Mesh target, table options optional )

Fits the given Shape, Mesh or Box to the screen, taking into account the camera's Projection mode. This function moves the camera back until the target fits on screen.

For example, to fit an object at the center of the screen, first have the camera look at the target (camera.Forward = target.Position - camera.Position) before calling this function.

Optional parameters:
- coverage indicates how much of the screen should be covered by the target. You can use this to adjust the fit, increasing this value will effectively zoom in on the target, decreasing it will zoom out.
- orientation may be used to force the use of a single dimension, instead of automatically choosing the limiting dimension. Valid values are "vertical" or "horizontal".

-- make the camera look at the shape
Camera.Forward = myShape.Position - Camera.Position

-- make the shape's bounding box cover approximately 60% of the screen, depending on perspective
Camera:FitToScreen(myShape, { coverage = 0.6 })

-- here's how to set independent constraints vertically and horizontally:
Camera:FitToScreen(myShape, { coverage = 0.8, orientation = "horizontal" })
local d = (Camera.Position - myShape.Position).SquaredLength
local p = Camera.Position:Copy() -- save position for horizontal fit
Camera:FitToScreen(myShape, { coverage = 0.6, orientation = "vertical" })
local d2 = (Camera.Position - myShape.Position).SquaredLength
if d > d2 then -- if horizontal fit is better, go back to the saved position
  Camera.Position = p
end

Converts unsigned normalized screen coordinates (Number2 between {0, 0} (bottom left) and {1, 1} (top right)) into a Ray based on this camera projection.

Converts a world position (Number3) into unsigned normalized screen coordinates through this camera projection. The returned Number2 coordinates are between {0, 0} (bottom left corner of the screen) and {1, 1} (top right corner of the screen).

⚠️ WorldToScreen can return nil if the given position can't be seen by the camera (not on screen).

local screenCoords = Camera:WorldToScreen(someObject.Position)
-- screenCoords is a Number2 between {0, 0} (bottom left) and {1, 1} (top right),
-- it can be nil if someObject.Position can't be seen by the camera.
if screenCoords ~= nil then 
  -- to obtain screen point values, multiply by Screen.Size:
  local screenPos = screenCoords * Screen.Size

  -- this is useful when positioning UI elements:
  local text = require("uikit"):createText("Hello, world!")
  text.pos = { -- text's anchor is bottom left, offsetting to center
    screenPos.X - text.Width * 0.5,
   screenPos.Y - text.Height * 0.5
  }
end

Inherited from Object

Hide

nil Load ( string itemName, function callback, table config optional )

Loads the given item asynchronously and calls the callback once done. The parameter itemName follows the usual naming convention user.item.

This is a function of the global Camera, to be called as Object:Load(itemName, callback, config).

The config table options are as follows,
- mutable allows to create the item shapes as MutableShape instead of Shape. Default false.
- bakedLight allows to generate baked lighting for the item shapes. Default false.

nil AddChild ( Object child, boolean keepWorld optional )

Adds given Object as a child. Object extensions like Shape or MutableShape are naturally accepted too.

The keepWorld optional parameter, false by default, dictates whether to maintain the child's world or local position and rotation. Keeping world will ensure the object doesn't move in the scene, adjusting its local position/rotation accordingly; keeping local will have the object move in the scene in order to maintain an equivalent local position/rotation relative to its new parent.

local o = Object()
local myShape = Shape(Items.someuser.someitem)
o:AddChild(myShape)
nil RemoveChild ( Object child, boolean keepWorld optional )

Unsets parent/child relationship with child parameter. The child ends up being deleted if it has no other references.

The keepWorld optional parameter, false by default, dictates whether to maintain the child's world or local position and rotation. Keeping world will ensure the object doesn't move in the scene, adjusting its local position/rotation accordingly; keeping local will have the object move in the scene in order to maintain an equivalent local position/rotation relative to its new parent.

o:RemoveChild(someChildObject)
nil RemoveChildren ( boolean keepWorld optional )

Unsets parent/child relationship with all children. Individual children end up being deleted if they have no other references.

The keepWorld optional parameter, false by default, dictates whether to maintain the child's world or local position and rotation. Keeping world will ensure the object doesn't move in the scene, adjusting its local position/rotation accordingly; keeping local will have the object move in the scene in order to maintain an equivalent local position/rotation relative to its new parent.

o:RemoveChildren()
nil Recurse ( function callback, table config optional )

Iterates over all descendants of Camera and calls the callback function for each.

The callback function is called with the descendant as the only argument.

The config table accepts two boolean options:
- deepFirst: if true, traverses depth-first instead of root-first. Default false.
- includeRoot: if true, includes Camera in the recursion. Default false.

o:Recurse(function(descendant)
  print(descendant)
end, { includeRoot = true })
Object FindFirst ( function searchFunction, table config optional )

Returns the first descendant Object for which the search function returns true.
If no descendant is found, returns nil.

The search function is called with the descendant as the only argument.

The config table accepts two boolean options:
- deepFirst: if true, traverses depth-first instead of root-first. Default false.
- includeRoot: if true, includes Camera in the recursion. Default false.

local leaf = oakTree:FindFirst(function(o) return o.Name == "leaf" end)
if leaf then
  print("found a leaf:", leaf)
end
table Find ( function searchFunction, table config optional )

Returns all descendants Objects for which the search function returns true.
If no descendant is found, returns an empty table.

The search function is called with the descendant as the only argument.

The config table accepts two boolean options:
- deepFirst: if true, traverses depth-first instead of root-first. Default false.
- includeRoot: if true, includes Camera in the recursion. Default false.

local leaves = oakTree:Find(function(o) return o.Name == "leaf" end)
for i, leaf in leaves do
  print("leaf #" .. i .. ":", leaf)
end

The most efficient way to dispose of an Object for good.

Calling Destroy removes the Object and all its descendants from the World.
Metadata associated with all of these Objects also gets removed.

Once destroyed, the Objects can't be used anymore.

o:Destroy()

Get child Object at index.

if o.ChildrenCount > 0 then
  print(o:GetChild(1)) -- prints first child
end

Get Camera's parent.

print(myObject:GetParent())
nil SetParent ( Object parent, boolean keepWorld optional )

Sets parent/child relationship with parent parameter. nil can be used to remove the Object from its parent.

The keepWorld optional parameter, false by default, dictates whether to maintain the child's world or local position and rotation. Keeping world will ensure the object doesn't move in the scene, adjusting its local position/rotation accordingly; keeping local will have the object move in the scene in order to maintain an equivalent local position/rotation relative to its new parent.

It's also a good practice to set child/parent relationships before setting positions.

local o = Object()
o:SetParent(Map) -- o is now a child of the map
-- (Map is an extension of Object)
nil RemoveFromParent ( boolean keepWorld optional )

Removes the Camera from its parent. Doesn't do anything if the Camera has no parent.

The keepWorld optional parameter, false by default, dictates whether to maintain the child's world or local position and rotation. Keeping world will ensure the object doesn't move in the scene, adjusting its local position/rotation accordingly; keeping local will have the object move in the scene in order to maintain an equivalent local position/rotation relative to its new parent.

o:RemoveFromParent()

Converts a local position to world coordinate system.

local p = Number3(1, 2, 3)
local pInWorldCoords = myObject:PositionLocalToWorld(p)

Converts a world position to local coordinate system.

local p = Number3(1, 2, 3)
local pInLocalCoords = myObject:PositionWorldToLocal(p)

Rotates the Camera in its own coordinates system.

o = Object()
-- rotate with provided Euler angle
o:RotateLocal({0, 0, math.pi / 2.0})

-- rotate along specified axis
o:RotateLocal(o.Forward, math.pi / 2.0)

Rotate the Camera in the World coordinates system.

o = Object()
-- rotate with provided Euler angles
o:RotateWorld({0, 0, math.pi / 2.0})

-- rotate along specified axis
o:RotateWorld(o.Forward, math.pi / 2.0)
-- same as o:RotateLocal({0, 0, 1}, math.pi / 2.0)

Converts a rotation from local to world relative to this object.

Converts a rotation from world to local relative to this object.

Returns true if the two Objects may collide with each other.

nil ApplyForce ( Object self, Number3 value )

Apply a force to Object, taking into account its Mass.

Resets to Camera's original collision box. For example, Player and Shape objects will revert to fitting their model bounding box.

nil Recurse ( function callback, table config optional )

Iterates over all descendants of Camera and calls the callback function for each.

The callback function is called with the descendant as the only argument.

The config table options are as follows,
- includeRoot whether to include Camera in the iteration. Default true.
- depth the maximum depth of the iteration. Default -1 (unlimited).
- deepFirst whether to iterate in depth-first order. Default false.

If you were to remove an object from its parent while recursing through it, the object removal will be delayed until the full recursion is completed.

o:Recurse(function(descendant)
  print(descendant.Name)
end, { includeRoot = true })
nil Copy ( table config optional )

Creates a copy of the object, including all its properties and current state.

To copy a composite object, you may call o:Copy({ recurse = true }). This will copy and replicate the full object hierarchy.

Properties

Shortcut to Camera.Color alpha.

A table that can be set to describe how the camera should behave: how it moves, rotates, collides with other objects, etc.
It can be set to nil to disable current behavior.

Fields accepted:
- positionTarget: Object to follow, or Number3 position to go to.
- positionTargetOffset: Fixed Number3 offset to apply to the target position.
- positionTargetBackoffDistance: distance (number) to backoff from the target position (considering collisions and current rotation).
- positionTargetMinBackoffDistance: minimum distance (number) to backoff from the target, going through colliders if needed, also the minimum distance user can set using mouse wheel or pinch gesture.
- positionTargetMaxBackoffDistance: maximum distance (number) user can set using mouse wheel or pinch gesture.
- rotationTarget: Object's rotation or Rotation to rotate to.
- rigidity: number, generally between 0 and 1, setting how fast the camera moves to the target.
- collidesWithGroups: CollisionGroups that the camera will collide with.

More fields will be added in future updates! But this set already allows to create a lot of different camera behaviors.
Also, you can always set Camera.Behavior = nil and implement your own logic manipulating Camera as any other Object.

-- a "third person" camera, following the player and looking in the same direction as its head
Camera.Behavior = {
  positionTarget = Player, -- camera goes to that position (or position of given object)
  positionTargetOffset = { 0, 14, 0 }, -- applying offset (looking right above the head)
  positionTargetBackoffDistance = 40, -- camera tries to backoff that distance, considering collisions
  positionTargetMinBackoffDistance = 20,
  positionTargetMaxBackoffDistance = 100,
  rotationTarget = Player.Head, -- camera rotates to that rotation (or rotation of given object)
  rigidity = 0.5, -- how fast the camera moves to the target
  collidesWithGroups = nil, -- camera collides with objects in these groups
}

-- a camera to follow vehicles, less rigid and looking a bit from above the vehicle
Camera.Behavior = {
  positionTarget = plane,
  positionTargetOffset = { 0, 5, 0 },
  positionTargetBackoffDistance = 70,
  positionTargetMinBackoffDistance = 20,
  positionTargetMaxBackoffDistance = 200,
  rotationTarget = plane,
  rotationTargetOffset = Rotation(math.rad(10), 0, 0), -- tilting 10 degrees down
  rigidity = 0.25,
  collidesWithGroups = nil,
}

Multiplicative color applied on camera final render.

Far plane of the camera projection.

Can be set to change Camera's minimum field of view, default value is 60 degrees.

The minimum field of view equates to the vertical field of view in landscape, or to the horizontal field of view in portrait. This is to ensure a consistent look&feel between screen orientations or aspect ratios.

Camera.FieldOfView = 40.0

Height of the camera projection.

number HorizontalFOV read-only

Returns the horizontal field of view, depending on current screen orientation. This is based on the minimum field of view FieldOfView.

Integer or table of integers between 1 and 12. Only objects in one of the specified layers are rendered by the camera.

Near plane of the camera projection.

Whether the camera is active or not.

The projection mode can be one of ProjectionMode.Perspective (by default) or ProjectionMode.Orthographic.

Note that it can be changed at any time.

Height of the camera screen target, expressed in screen points.

Width of the camera screen target, expressed in screen points.

X component of the camera screen target bottom-left corner, expressed in screen points.

Y component of the camera screen target bottom-left corner, expressed in screen points.

number VerticalFOV read-only

Returns the vertical field of view, depending on current screen orientation. This is based on the minimum field of view FieldOfView.

Integer between 1 and 255 used to order multiple cameras. Additional cameras created in Lua have a default value of 127. The main Camera provided by Blip engine has a default value of 0.

Note that as of version 0.1.1, setting an orthographic camera's view order to be rendered before a perspective camera will make it use render scaling instead of points scaling (see Camera). This may be addressed in future updates.

Width of the camera projection.

Inherited from Object

Hide

Camera's constant acceleration in world coordinates per second squared.

⚠️ Acceleration only affects Camera when Camera.Physics is PhysicsMode.Dynamic.

-- Acceleration can be used to compensate gravity: 
myObject.Acceleration = -Config.ConstantAcceleration
-- myObject's acceleration is now the invert of 
-- Config.ConstantAcceleration, cancelling it.

Collision groups the Camera belongs to.

⚠️ It doesn't mean the Camera will collide with other Objects in these groups.

If the Camera belongs to group number 3 for example, it means all Objects that have group number 3 in their Object.CollidesWithGroups property will collide with it.

By default:
- Objects collide with the Map and other Objects
- Players collide with the Map only

That can all be configured differently depending on your needs.

local object1 = Object()
local object2 = Object()
object1.Physics = PhysicsMode.Dynamic
object2.Physics = PhysicsMode.Dynamic

-- making sure 2 objects collide with each other
-- NOTE: by default:
-- Map.CollisionGroups == {1},
-- Player.CollisionGroups == {2},
-- Object.CollisionGroups == {3}
object1.CollisionGroups = {5}
object2.CollisionGroups = {5}
object1.CollidesWithGroups = {1, 5} -- collides with Map + objects in group 5
object2.CollidesWithGroups = {1, 5} -- collides with Map + objects in group 5

-- would also work this way if you don't 
-- remember Map's group (which can be changed too by the way)
object1.CollidesWithGroups = Map.CollisionGroups + {5}

-- making an object collides with the Map and Players
local object = Object()
object.CollidesWithGroups = Map.CollisionGroups + Player.CollisionGroups

-- for Player (local player) to collide with other players and the Map
Player.CollidesWithGroups = Map.CollisionGroups + Player.CollisionGroups

Collision groups the Camera collides with.

By default:
- Objects collide with the Map and other Objects
- Players collide with the Map and the Objects

That can all be configured differently depending on your needs.

local object = Object()

-- It's not mandatory to change Physics value.
-- (default value is PhysicsMode.Static)
-- An object with Physics set to PhysicsMode.Static contributes 
-- to the physics simulation as a static item (can't be moved)
object.Physics = PhysicsMode.Dynamic

-- making an object collide with the Map and Players
object.CollidesWithGroups = Map.CollisionGroups + Player.CollisionGroups

-- for an Object to collide with other objects only
-- (won't collide with the map)
object.CollidesWithGroups = object.CollisionGroups

-- for Player (local player) to collide with other players and the Map
Player.CollidesWithGroups = Map.CollisionGroups + Player.CollisionGroups

-- making sure 2 objects collide with each others
-- NOTE: by default:
-- Map.CollisionGroups == {1},
-- Player.CollisionGroups == {2},
-- Object.CollisionGroups == {3}
local object1 = Object()
local object2 = Object()
object1.CollisionGroups = {5}
object2.CollisionGroups = {5}
object1.CollidesWithGroups = {1, 5} -- collides with Map + objects in group 5
object2.CollidesWithGroups = {1, 5} -- collides with Map + objects in group 5

-- would also work this way if you don't 
-- remember Map's group (which can be changed too by the way)
object1.CollidesWithGroups = Map.CollisionGroups + {5}

Sets the simulation mode for this object, it can be one of the following:
- PhysicsMode.Disabled: excluded from all physics features.
- PhysicsMode.Trigger: Camera's collision box is available for casts and collision callbacks, and is passed through by other dynamic objects.
- PhysicsMode.TriggerPerBlock: if Camera is a Shape, its model blocks are available for casts and collision callbacks, and is passed through by other dynamic objects.
- PhysicsMode.Static: Camera's collision box is available for casts, collision callbacks, and acts as an obstacle for other dynamic objects.
- PhysicsMode.StaticPerBlock: if Camera is a Shape, its model blocks are available for casts, collision callbacks, and act as obstacles for other dynamic objects.
- PhysicsMode.Dynamic: Camera's world-aligned collision box is available for casts, collision callbacks, may act as obstacles for other dynamic objects, and is itself fully simulated. When setting this mode, any children that may collide with the object will be automatically set to PhysicsMode.Disabled.

By default, players are PhysicsMode.Dynamic, shapes are PhysicsMode.Static, all other objects are PhysicsMode.Disabled.

You may use Dev.DisplayColliders to visualize each object's collision settings.

⚠️ When set to PhysicsMode.Disabled, Camera.Velocity & Camera.Motion are set to {0,0,0}.

nil by default. Can be set to a function that will be triggered when this object begins a collision with another object.

The function is called with 3 parameters:
- the object the callback was set for,
- the other actor in the collision,
- the world normal of the hit surface.

Note: it's not necessary to use all 3 parameters.

object.OnCollisionBegin = function(self, other, normal)
  print("collision began between", self, " and ", other, " with world normal ", normal)
end

nil by default. Can be set to a function that will be triggered every frame where this object remains in contact with another object.

Like OnCollisionBegin, this function has 3 arguments: self, other, normal.

nil by default. Can be set to a function that will be triggered when the Camera ends colliding with another Object.

The function is called with 2 parameters: the object the callback was set for and the other actor in the collision.

object.OnCollisionEnd = function(self, other)
  print("collision ended between", self, "and", other)
end

Position of the Camera in the world.

local o = Object()
-- places the object where the local player is
o.Position = Player.Position
boolean IsOnGround read-only

true when the Camera is not falling.

⚠️ IsOnGround only makes sense when Camera.Physics is PhysicsMode.Dynamic.

Can be set to true for the Camera to be hidden recursively, meaning Camera and all of its children are hidden.

Nothing else changes, the Camera remains in the scene and it keeps being affected by the simulation (collisions, etc.).

Can be set to true for the Camera to be hidden individually.

Nothing else changes, the Camera remains in the scene and it keeps being affected by the simulation (collisions, etc.).

Size in world units of the shadow cookie projected under the Camera, default is 0.0 (disabled).
The shadow cookie, also called blob shadow, is a square texture acting as a cheap alternative to projected shadows.

If this value is strictly positive, shadow cookies will be displayed when:
- the scene has no light source,
- the scene has light sources, but they are disabled because the client is using lower quality settings

Shadow cookies can be used as a fallback to your scene shadows for players with low quality settings, of course, you can also use them instead of shadows as a design choice.

Local position of the Camera relative to its parent.

All of Camera's ancestors local transformations are combined to obtain the Camera "world position" (Object.Position), the Object's final position.

Rotation of the Camera in the world (as seen on screen).

While it usually works for simple operations (like Rotation.X = Rotation.X + someAngle), we advise you to use Number3.Rotate to rotate an object around X, Y & Z axis.

You can also set unit vectors like Camera.Up, Camera.Right or Camera.Forward to orient your object.

local o = Object()
o.Rotation = {0, math.pi, 0}
-- o revolved half a turn on Y axis

-- another way to rotate the object:
o.Forward:Rotate({0, 0, math.pi / 2})
o.Forward = Camera.Forward

Tick is a function executed ~30 times per second when set (nil by default). Provides the Camera and elapsed time in seconds as parameters.

-- executed ~30 times per second on each user device
myObject.Tick = function(object, dt)
  print("elapsed:", dt, "seconds")
end

Local rotation of the Camera relative to its parent.

All of Camera's ancestors local transformations are combined to obtain the "world rotation" (Object.Rotation), the Object's final rotation.

Velocity of the Camera in world coordinates per second.

⚠️ Velocity only affects Camera when Camera.Physics is PhysicsMode.Dynamic.
Whenever Physics is set to PhysicsMode.Disabled, Velocity is set to {0,0,0}.

-- makes myObject jump:
myObject.Velocity.Y = 100

Be aware, this Motion property is a hack regarding laws of physics. (sorry Isaac)

But it's very practical to move objects without worrying about forces at play.

This is what's being used by default when you're moving around with your avatar (see Client.DirectionalPad). It's the reason why you can stop moving horizontally while in the air.

Basically, Motion is an instantaneous displacement that contributes to moving Camera every frame, without changing Camera.Velocity directly.

Motion is expressed in world coordinates per second.

⚠️ Motion only affects Camera when Camera.Physics is PhysicsMode.Dynamic.
Whenever Physics is set to PhysicsMode.Disabled, Motion is set to {0,0,0}.

local speed = 10
myObject.Motion = Camera.Forward * speed
-- myObject will move in the same direction the camera is currently facing.
-- If the Camera rotates after this, it won't change where myObject is heading.

Scale of the Object, in its parent.

Nested Object local scales are combined to obtain the "world scale" (Object.LossyScale), the Object's final scale.

myObject.LocalScale = 2 -- the Object is now 2 times bigger
topLevelObject.LocalScale = 2
local o = Object()
o.LocalScale = 0.5
topLevelObject:AddChild(o) -- o becomes a child of topLevelObject
-- o ends up being displayed with a scale of 1
number LossyScale read-only

Convenience property that attempts to match the actual world scale as much as it can. Note that Objects that have multiple levels of nested rotations and scales will return a skewed lossy scale.

The mass of the Object determines how much a given force can move it and whether or not another object can be pushed by it. It cannot be zero, a neutral mass is a mass of 1.

The combined friction of 2 Objects in contact represents how much the moving Object will be able to slide along the colliding Object.

It is a rate between 0 (full slide, no friction) and 1 (maximum friction). Values equal to or lower than 0 will keep or increase momentum, like sliding on ice. Values higher than 1 means a faster stop, up to a value of 2 to ensure a full stop on contact regardless of the colliding Object's own friction.

[Object.Friction] can be set per-face by providing a table with any combination of the following keys : right, left, front, back, top, bottom, other.
For example, to set the friction on the bottom face of an object's collider to 0 and 0.2 on every other faces, you could set, object.Friction = { bottom=0, other=0.2 }.

The combined bounciness of 2 Objects in contact represents how much of the moving Object's velocity is produced after being in contact with the colliding Object, it is a rate between 0 (no bounce) and 1 (100% of the velocity bounced). Values higher than 1 are allowed and will create an increasing momentum at each bounce (try at your own risk).

[Object.Bounciness] can be set per-face by providing a table with any combination of the following keys : right, left, front, back, top, bottom, other.
For example, to set the bounciness on the side faces of an object's collider to 0.2 and 0 on top and bottom faces, you could set, object.Bounciness = { top=0, bottom=0, other=0.2 }.

All Objects have a collision box that represents the space occupied in the scene with regards to collisions. For Shapes and Players, the collision box is updated with their bounding box. For Objects, it is a 1-cube by default after physics was enabled for the first time.

Returns number of child Objects.

Up is a unit vector (vector with a length of 1). It determines which direction is "up" for the Camera.

Setting it is a way to rotate the Camera.

Right is a unit vector (vector with a length of 1). It determines which direction is "right" for the Camera.

Setting it is a way to rotate the Camera.

Forward is a unit vector (vector with a length of 1). It determines which direction is "forward" for the Camera.

Setting it is a way to rotate the Camera.

Left is a unit vector (vector with a length of 1). It determines which direction is "left" for the Camera.

Setting it is a way to rotate the Camera.

Down is a unit vector (vector with a length of 1). It determines which direction is "down" for the Camera.

Setting it is a way to rotate the Camera.

Backward is a unit vector (vector with a length of 1). It determines which direction is "backward" for the Camera.

Setting it is a way to rotate the Camera.