PcoWSkbVqDnWTu_dm2ix
Controlling the Player's Camera
Part 2 - Creating a Side-Scrolling Camera
Controlling the Player's Camera
Part 2 - Creating a Side-Scrolling Camera

A side-scrolling view keeps the camera at a fixed position relative to the side of the character, giving the world a two-dimensional feel.

alt

Scripting the Camera

  1. Expand StarterPlayer, and in StarterPlayerScripts add a LocalScript named CameraManager.

    alt

  2. At the top of the script, get the Players service, and then in a new variable get the local player.

    local Players = game:GetService("Players")
    
    local player = Players.LocalPlayer
  3. Create a function called updateCamera. This will hold the logic needed to get and set a new position for the camera.

    local Players = game:GetService("Players")
    
    local player = Players.LocalPlayer
    
    local function updateCamera()
        
    end
  4. Inside the function, get the player’s character model and check if it exists by using an if statement.

    local Players = game:GetService("Players")
    
    local player = Players.LocalPlayer
    
    local function updateCamera()
        local character = player.Character
        if character then
    
        end
    end
    Client-side Camera

    Only a player can see their own camera configuration, so it is always controlled using LocalScripts.


Pointing the Camera

All character models contain a part named HumanoidRootPart, which can be used to get the character’s position in the world. This will be the position the camera points at.

  1. Use FindFirstChild to get the HumanoidRootPart and check it exists using an if statement.

    local Players = game:GetService("Players")
    
    local player = Players.LocalPlayer
    
    local function updateCamera()
        local character = player.Character
        if character then
            local root = character:FindFirstChild("HumanoidRootPart")
            if root then
    
            end
        end
    end
  2. The position of the HumanoidRootPart is actually 2 studs below the player’s head. To fix this, add a new Vector3 with a height of 2 studs to the root’s position.

    local Players = game:GetService("Players")
    
    local player = Players.LocalPlayer
    
    local HEIGHT_OFFSET = 2
    
    local function updateCamera()
        local character = player.Character
        if character then
            local root = character:FindFirstChild("HumanoidRootPart")
            if root then
                local rootPosition = root.Position + Vector3.new(0, HEIGHT_OFFSET, 0)
            end
        end
    end

Setting the Camera Position

The camera will also need a position. To give the player’s view a 2D side-scrolling look, the camera will need to look directly at the side of the character.

  • Place the camera to the side of the player by adding depth to just the Z axis of the camera’s position using a Vector3.

    local player = Players.LocalPlayer
    
    local CAMERA_DEPTH = 24
    local HEIGHT_OFFSET = 2
    
    local function updateCamera()
        local character = player.Character
        if character then
            local root = character:FindFirstChild("HumanoidRootPart")
            if root then
                local rootPosition = root.Position + Vector3.new(0, HEIGHT_OFFSET, 0)
                local cameraPosition = Vector3.new(rootPosition.X, rootPosition.Y, CAMERA_DEPTH)
            end
        end
    end
    

Update CurrentCamera

Now that the variables for the camera’s position and the camera’s target are ready, it’s time to update the camera’s position. The player’s camera can be accessed through the CurrentCamera property of Workspace. The camera has a CFrame property to determine its position.

You can use CFrame.lookAt to update the camera. It takes two positions and creates a CFrame located at the first position pointed towards the second.

  • Use CFrame.lookAt to create a CFrame that is positioned at cameraPosition and pointed toward rootPosition.

    local player = Players.LocalPlayer
    local camera = workspace.CurrentCamera
    
    local CAMERA_DEPTH = 24
    local HEIGHT_OFFSET = 2
    
    local function updateCamera()
        local character = player.Character
        if character then
            local root = character:FindFirstChild("HumanoidRootPart")
            if root then
                local rootPosition = root.Position + Vector3.new(0, HEIGHT_OFFSET, 0)
                local cameraPosition = Vector3.new(rootPosition.X, rootPosition.Y, CAMERA_DEPTH)
                camera.CFrame = CFrame.lookAt(cameraPosition, rootPosition)
            end
        end
    end

Sync the Camera

The last step is to run this function repeatedly to keep the camera in sync with the player. The image the player sees is constantly refreshing. The split second it takes to do all of the calculations necessary is called the render step.

RunService:BindToRenderStep makes it simple to execute a function on every frame by accepting these three parameters:

  • name - The name of this binding, which should be unique so it won’t clash with other functions of the same name.
  • priority - The higher the number, the higher the priority. This function should run after Roblox’s default camera update, so the priority is set to 1 level higher than the internal camera’s RenderPriority.
  • function - The function to be bound to the render step.
  1. Use RunService:BindToRenderStep to bind the updateCamera function to the render step.

    local Players = game:GetService("Players")
    local RunService = game:GetService("RunService")
    
    local player = Players.LocalPlayer
    local camera = workspace.CurrentCamera
    
    local CAMERA_DEPTH = 24
    local HEIGHT_OFFSET = 2
    
    local function updateCamera()
        local character = player.Character
        if character then
            local root = character:FindFirstChild("HumanoidRootPart")
            if root then
                local rootPosition = root.Position + Vector3.new(0, HEIGHT_OFFSET, 0)
                local cameraPosition = Vector3.new(rootPosition.X, rootPosition.Y, CAMERA_DEPTH)
                camera.CFrame = CFrame.lookAt(cameraPosition, rootPosition)
            end
        end
    end
    
    RunService:BindToRenderStep("SidescrollingCamera", Enum.RenderPriority.Camera.Value + 1, updateCamera)
  2. Playtest your code. Use the A and D keys to move your character from side to side.


Previous Page Getting Started Next Page Creating an Isometric Camera