How to Add "Weight" to the Camera [Camera Tutorial]

Awesome, here’s something you can definitely use Math for Game Programmers: Juicing Your Cameras With Math - YouTube

2 Likes

is there a way to make it work with shift lock?(in the click, I activate shift lock on -00:02, in case the video doesn’t load, it basically makes the character be sideways while running forward)

1 Like

Humanoid.AutoRotate?

Thanks for pointing that out. I added a section at the bottom to fix this

1 Like

I am kind of new to vectors and CFrame but what does this mean and why does this work?

I have a guide for CFrames if you wanted to learn in general, but I’ll explain this thing specifically: A CFrame encodes the position and orientation of parts and cameras. The LookVector of a cameras CFrame is the direction of it’s view, and the LookVector of a part is the direction it’s front side is facing.

Basically what this code does is set the root part’s CFrame so that it’s position stays the same, but its front side points in the same horizontal direction as the camera. The CFrame.lookAt() constructor takes the position as the first argument, and a point in space to look at in the 2nd argument. For the second argument I took the horizontal component of the camera LookVector and added it to the position of the root part which creates a point in space which is displaced from the character in the direction we want them to look

1 Like

Hello @xXSanrioSlayer99, thank you for taking your time to make this tutorial for us.
I didn’t have any problems with the code. But, as I’m an amateur programmer, I couldn’t figure out a way to implement my camera offset values (0,0.05,0) to our new CurrentCamera.
Can you help me on this? Thanks!

1 Like

All you have to do is offset the goal position of the lerp based on your chosen offset:

We originally have this:

local function updateSubject()
	subject.Position = subject.Position:Lerp(rootPart.Position,1/WEIGHT)
end

but instead of lerp to rootPart.Position you can add your offset to get this:

local function updateSubject()
	local offset = Vector3.new(0, 0.05, 0)
    subject.Position = subject.Position:Lerp(rootPart.Position + offset,1/WEIGHT)
end

this will make it so the camera works to point towards the root part, plus your offset value.

1 Like

Question if i go in first person the whole thing breaks is there any way to fix this?

Whoops that was a big oversight by me. I added a section to disable camera weight while in first person

1 Like

I am struggling to add an offset to the camera module, I added the following to add Y offset of 3 without luck. Welp!

local myChar = script.Parent
local myHum = myChar.Humanoid
myHum.CameraOffset = Vector3.new(0,3,0)

Also, I m so so very happy with this module, BIG thank you! and if you have time and if you are interested, I would love to show you what I am doing with it :slight_smile:

I’m having a bit of a struggle with the first person stuff. Everything works great at the start but once I go into first person then come out, the camera weighting stops working. I got no errors and would be grateful if you could point me in the right direction.

Source Code
local RUN_SERVICE = game:GetService("RunService")
local USER_INPUT_SERVICE = game:GetService("UserInputService")

local Cam = workspace.CurrentCamera

local Subject = script:WaitForChild("CameraSub")
local Head = script.Parent:WaitForChild("Head")
local Root = script.Parent:WaitForChild("HumanoidRootPart")
local Humanoid = script.Parent:WaitForChild("Humanoid")

Subject.Position = Head.Position
Cam.CameraSubject = Subject

local CamWeight = 60

local function UpdateSub()

	if (Cam.CFrame.Position - Subject.Position).Magnitude < 1 or (Cam.CFrame.Position - Head.Position).Magnitude < 1 then
		Cam.CameraSubject = Humanoid
		Subject.Position = Head.Position

	else

		Subject.Position = Subject.Position:Lerp(Head.Position, 1/CamWeight)
		if USER_INPUT_SERVICE.MouseBehavior == Enum.MouseBehavior.LockCenter then
			local Look = Vector3.new(Cam.CFrame.LookVector.X, 0, Cam.CFrame.LookVector.Z)
			Root.CFrame = CFrame.lookAt(Root.Position, Root.Position + Look)
		end
	end
end

RUN_SERVICE:BindToRenderStep("UpdateSub", Enum.RenderPriority.Camera.Value, UpdateSub)

you forgot to set camera subject back to the subject part in the “else” part of the update function.

works great but up close there’s still a slight stutter/jitter. how do you fix that?

local RunService = game:GetService("RunService")

local camera = workspace.CurrentCamera
local head = script.Parent:WaitForChild("Head")
local subject = script:WaitForChild("Subject")

subject.Position = head.Position
camera.CameraSubject = subject

local WEIGHT = 20

local function updateSubject()
	subject.Position = subject.Position:Lerp(head.Position,1/WEIGHT)
end

RunService:BindToRenderStep("UpdateSubject", Enum.RenderPriority.Camera.Value + 1, updateSubject)
2 Likes

this going to be perfect for that one bmx game

local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")

local CurrentCamera = workspace.CurrentCamera
local Humanoid = script.Parent:WaitForChild("Humanoid")

local Head = script.Parent:WaitForChild("Head")
local HumanoidRootPart = script.Parent:WaitForChild("HumanoidRootPart")

local Subject = script:WaitForChild("Subject")

local HeadPosition = Head.Position
local SubjectPosition = Subject.Position

SubjectPosition = HeadPosition
CurrentCamera.CameraSubject = Subject

local SubjectWeights_Horizontal = 10
local SubjectWeights_Vertical = 20

local function UpdateSubject()
	local OffsetVectors = Vector3.new(0, 0.6, 0)
	local HorizontalPosition = Vector3.new(SubjectPosition.X, 0, SubjectPosition.Z):Lerp(Vector3.new(HeadPosition.X, 0, HeadPosition.Z) + OffsetVectors, 1/SubjectWeights_Horizontal)
	local VerticalPosition = Vector3.new(0, SubjectPosition.Y, 0):Lerp(Vector3.new(0, HeadPosition.Y, 0) + OffsetVectors, 1/SubjectWeights_Vertical)
	
	SubjectPosition = HorizontalPosition + VerticalPosition
	
	if UserInputService.MouseBehavior == Enum.MouseBehavior.LockCenter then
		local LookVectors = Vector3.new(CurrentCamera.CFrame.LookVector.X, 0, CurrentCamera.CFrame.LookVector.Z)
		HumanoidRootPart.CFrame = CFrame.lookAt(HumanoidRootPart.Position, HumanoidRootPart.Position + LookVectors)
		if (CurrentCamera.CFrame.Position - SubjectPosition).Magnitude < 1 or (CurrentCamera.CFrame.Position - HeadPosition).Magnitude < 1 then
			CurrentCamera.CameraSubject = Humanoid
			SubjectPosition = HeadPosition
		else
			CurrentCamera.CameraSubject = Subject
			SubjectPosition = HorizontalPosition + VerticalPosition
		end
	end
end

RunService:BindToRenderStep("UpdateSubject", Enum.RenderPriority.Camera.Value, UpdateSubject)

It seems that I have ran into an issue, any idea why this is broken? I mean it seems to work but the camera doesn’t actually follow the player anymore?

It seems you are updating the variable SubjectPosition rather than the actual position of the subject part, so instead of changing the value of Subject.Position you’re just changing what value is stored in the SubjectPosition variable.

So inside the loop you should replace SubjectPosition with Subject.Position so that it is actually changing the position property. Also inside the loop you need to change HeadPosition to Head.Position so that you’re referring to the current position of the head rather than what the head position was when you originally defined that variable.

1 Like

Unfortunately I think that’s just a limitation of this method :confused:

Ah, I see, alright well I’ll make the changes as soon as I arrive home but thanks a lot. Needed that help! ^^

This gives a choppy effect when rotating camera or just walking