Camera Pushing and Pulling

Hello, I’ve been recently working on a dolly track camera I have made it so the sway works (The camera will face where the player is)

camera.CFrame = CFrame.new(workspace.CameraOne.CFrame.Position, Character.HumanoidRootPart.Position)

now I want it to make it so it follows the player like this:

Any help is appreciated!

1 Like

Perhaps add an offset that’ll keep the camera a fixed distance from the target and if it’s farther or closer than that target you can lerp the position back to a more desirable one?

1 Like

My thought process on this:

  1. Camera should have it’s own independent CFrame position, not reliant on the players position.
  2. Have the camera always looking at the player.
  3. Compute the angle of the Camera’s position and the Player’s head position. This should ignore the Y axis.
  4. Use this CFrame: CFrame.new(head.Position)*CFrame.Angles(0,<COMPUTED_ANGLE>,)*CFrame.new(0,0,-<DISTANCE_AWAY_FROM_HEAD>)

This CFrame uses a more simple approach and may not work perfectly. You might have to instead do something like this:

CFrame.new(Camera.Position)*CFrame.Angles(0,<COMPUTED_ANGLE>,0)*CFrame.new(0,0,<STUDS_TO_MOVE_UP>)

This can become very complicated. For example, the distance away from head could be a clamped distance between 2 and 5 studs. Once the player is over 5 studs away, you would move the camera twords the player. If the player is less than two studs away, you move the camera away.

You also might have to account for objects too, so don’t forget that. Shoot rays from the players head to the camera, and if something is in the way, you need to adjust.

Good luck!

2 Likes

Please may you elaborate, I am confused on how to get the computed angle.

I created a script which works perfect except for the moving, I’m stuck on that part

local Player = game.Players.LocalPlayer
local camera = workspace.CurrentCamera

game:GetService("RunService").RenderStepped:Connect(function()
		local DistanceFromHead = (workspace.Camera.CFrame.Position - Player.Character.Head.Position).magnitude
		local Distance = CFrame.new(Player.Character.Head.Position) * CFrame.Angles(0, 1, 0) * CFrame.new(0,0,DistanceFromHead) 

		camera.CFrame = Distance
end)

Wait I think I somehow found out how to do it:

local Player = game.Players.LocalPlayer
local camera = workspace.CurrentCamera
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local Folder = game.Workspace.Folder

game:GetService("RunService").RenderStepped:Connect(function()
		local DistanceFromHead = (workspace.Camera.CFrame.Position - Player.Character.Head.Position).magnitude
		local Distance = CFrame.new(Player.Character.Head.Position) * CFrame.Angles(0, 1, 0) * CFrame.new(0,0,DistanceFromHead) 

		camera.CFrame = Distance
		
		for i,v in pairs(Folder:GetChildren()) do
			if camera:WorldToViewportPoint(v.Position) then
				if (Player.Character.HumanoidRootPart.Position - v.Position).Magnitude <= 10 then
					v.Parent = ReplicatedStorage.Folder 
				end
			end
		end
	
		for i,v in pairs(ReplicatedStorage.Folder:GetChildren()) do
			if (Player.Character.HumanoidRootPart.Position - v.Position).Magnitude > 10 then
				v.Parent = Folder 
			
		end
	end
end)

Thank you!, It might need some adjustments so I’ll get to work on that and tell you how it works out.

You are going to have to use lerp here. You have to face the player then move the camera to that distance away from the player.

-- RenderStepped
local TargetPosition = (Camera.CFrame.Position - Character.Head.Position).Unit * Distance  + Player.Position-- the distance form player added to players position
Camera.CFrame = Camera.CFrame:Lerp(
    CFrame.lookAt(
        TargetPosition,
        Character.Head.Position
    ),
    DeltaTime * CameraLerpSpeed -- You can change this if you'd like
)

Result: https://gyazo.com/6c2e89197a2612e6ace9c60809cb9ba4

Extra points if you can add a way to change the distance in game

*Distance

What distance should I times it by?

It keeps going into the players foot, and lerping down. This is what I got:

game:GetService("RunService").RenderStepped:Connect(function()
		local DistanceFromHead = (workspace.Camera.CFrame.Position - Player.Character.Head.Position).magnitude
		local Distance = CFrame.new(Player.Character.Head.Position) * CFrame.Angles(0, 1, 0) * CFrame.new(0,0,DistanceFromHead) 

		
	local TargetPosition = (Camera.CFrame.Position - Player.Character.Head.Position).Unit * Distance  + Player.Position
	Camera.CFrame = Camera.CFrame:Lerp(
		CFrame.lookAt(
			TargetPosition,
			Player.Character.Head.Position
		),
		4
	)
end)

Distance is a number. It represents the magnitude of the direction vector. Since you already have a unit vector you can multiply it with a number to get a desired distance in studs the camera will attempt to lerp to.

In my case I put 10 for Distance and 5 for Camera Lerp Speed which is self explanatory.

Also I should have told you to put the Character.Head.Position instead of Player.Position

This is the script I ended up with:

local Player = game.Players.LocalPlayer
local Camera = workspace.CurrentCamera
local CameraLerpSpeed = 5
local Distance = 10
local Character = Player.Character

game:GetService("RunService").RenderStepped:Connect(function(DeltaTime)
	local TargetPosition = (Camera.CFrame.Position - Character.Head.Position).Unit * Distance + Character.Head.Position
	Camera.CFrame = Camera.CFrame:Lerp(
		CFrame.lookAt(
			TargetPosition,
			Character.Head.Position
		),
		DeltaTime * CameraLerpSpeed 
)
end)

It doesn’t dolly like your one. It just moves with breathing.

I tried, it still doesn’t look like yours. Could you perhaps open source the game?

local Camera = workspace.CurrentCamera
local Character = game.Players.LocalPlayer.Character or game.Players.LocalPlayer.CharacterAdded:Wait()

game:GetService("RunService").RenderStepped:Connect(function(deltaTime)
	local TargetPosition = (Camera.CFrame.Position - Character.Head.Position).Unit * 10  + Character.Head.Position-- the distance form player added to players position
	Camera.CFrame = Camera.CFrame:Lerp(
		CFrame.lookAt(
			TargetPosition,
			Character.Head.Position
		),
		deltaTime * 5 -- You can change this if you'd like
	)
end)

Here is the full code.

Call it CameraScript and put it in StarterPlayerScript to get it to work.

1 Like