What would be the proper calculation to lerp to character head?

Hi, I was wondering if anyone knew what calculation I would need to use to lerp back to the character’s head.

I have already tried to find the offset by doing both:
(Camera.CFrame.Position - Camera.Focus.Position).Magnitude
&
(Camera.CFrame.Position - Camera.Focus.Position).Magnitude - CameraOffset.Z

The problem is, the first one sends the camera flying back, then once it’s set to custom at the end of the lerp, it jolts to the actual position. The second one works if the player is fully zoomed out, but then when you zoom in (before camera is offset), it jolts as well.

Here’s what I use to calculate CameraCFrame to send it back:

local Offset = Vector3.new(0, 0, (Camera.CFrame.Position - Camera.Focus.Position).Magnitude - self.CameraOffset.Z)
local CameraCFrame = CFrame.new(HumanoidRootPart.Position + Vector3.new(0, 2, 0)) * CFrame.Angles(0, AngleX, 0) * CFrame.Angles(AngleY, 0, 0) * CFrame.new(Offset)

CameraCFrame = Camera.CFrame:Lerp(CameraCFrame, CameraSettings.LerpingSpeed)
CameraCFrame = SendRaycast(CameraCFrame, HumanoidRootPart)

Camera.CFrame = CameraCFrame

Just to clarify, when I enable a tool, I change the Camera CFrame to an offset Offset = Vector3.new(CameraOffset * CurrentSide, CameraOffset.Y, CameraOffset.Z), then when I disable a tool, it should go back to the player’s head, then change back to Custom.

To manipulate the CFrame property of a Camera object (and it rendering correctly), its CameraType property must be set to Enum.CameraType.Scriptable. Are you doing this?

Yes, the camera is set to scriptable before the calculations are applied, that’s why I’m changing it back to custom at the end.

Alright cool. I’m a little confused by what effect exactly youre trying to achieve. Could you either send more code so I could replicate the effect myself or a short clip of the behavior?

1 Like

Yeah, this is roughly what I’m using (there’s other stuff included, but they don’t effect the camera.

local Camera = workspace.CurrentCamera
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local SelfPlayer = game:GetService("Players").LocalPlayer

local Tool = script.Parent

local AngleX, AngleY = 0,0
local Mouse = SelfPlayer:GetMouse()

local CurrentSide = 1 --Kept at 1 for now.

local CameraOffset = Vector3.new(2.35, 2, 8)
local AlignOffset = false

local Key = "Camera1"

local On = false


local RaycastParameters = RaycastParams.new()
RaycastParameters.IgnoreWater = true
RaycastParameters.FilterType = Enum.RaycastFilterType.Blacklist --Blacklists.

local CameraSettings = {				
	FieldOfView = 70;
	Sensitivity = 2.25;
	LerpingSpeed = 0.5;
}


local function Lerp(Alpha, Beta, Gamma)
	return Alpha + (Beta - Alpha) * Gamma
end

local function SendRaycast(CameraCFrame, HumanoidRootPart)
	RaycastParameters.FilterDescendantsInstances = {SelfPlayer.Character, workspace.RaycastIgnoreList}

	local Raycast = workspace:Raycast(HumanoidRootPart.Position, CameraCFrame.Position - HumanoidRootPart.Position, RaycastParameters)

	if Raycast then
		local ObstructionDisplacement = Raycast.Position - HumanoidRootPart.Position --Gets the displacement of the obstruction.
		local ObstructionPosition = HumanoidRootPart.Position + (ObstructionDisplacement.Unit * (ObstructionDisplacement.Magnitude - 0.1))

		local X,Y,Z,R00,R01,R02,R10,R11,R12,R20,R21,R22 = CameraCFrame:components() --Gets the pure CFrame components.
		CameraCFrame = CFrame.new(ObstructionPosition.X, ObstructionPosition.Y, ObstructionPosition.Z, R00, R01, R02, R10, R11, R12, R20, R21, R22)
	end
	return CameraCFrame
end


----


function Update()
	Camera.CameraType = Enum.CameraType.Scriptable

	local MouseDelta = UserInputService:GetMouseDelta() * CameraSettings.Sensitivity
	AngleX -= MouseDelta.X / Camera.ViewportSize.X
	AngleY -= MouseDelta.Y / Camera.ViewportSize.Y
	AngleY = math.rad(math.clamp(math.deg(AngleY), -70, 70))

	local Character = SelfPlayer.Character
	local HumanoidRootPart = (Character ~= nil) and (Character:FindFirstChild("HumanoidRootPart"))
	local Humanoid = (Character ~= nil) and (Character:FindFirstChild("Humanoid"))

	if HumanoidRootPart ~= nil and Humanoid.Health > 0 then

		local Offset
		local CameraCFrame

		if AlignOffset == false then
			UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
			Mouse.Icon = "http://www.roblox.com/asset/?id=7056880049"

			Offset = Vector3.new(CameraOffset.X * CurrentSide, CameraOffset.Y, CameraOffset.Z)
			CameraCFrame = CFrame.new(HumanoidRootPart.Position) * CFrame.Angles(0, AngleX, 0) * CFrame.Angles(AngleY, 0, 0) * CFrame.new(Offset)
		else
			Offset = Vector3.new(0, 0, (Camera.CFrame.Position - Camera.Focus.Position).Magnitude - CameraOffset.Z)
			CameraCFrame = CFrame.new(HumanoidRootPart.Position + Vector3.new(0, 2, 0)) * CFrame.Angles(0, AngleX, 0) * CFrame.Angles(AngleY, 0, 0) * CFrame.new(Offset)
		end

		CameraCFrame = Camera.CFrame:Lerp(CameraCFrame, CameraSettings.LerpingSpeed)
		CameraCFrame = SendRaycast(CameraCFrame, HumanoidRootPart)

		Camera.CFrame = CameraCFrame
	end
end




Tool.Equipped:Connect(function()
	if On == true then return end
	
	local CameraCFrame = Camera.CFrame
	local X,Y,Z = CameraCFrame:ToOrientation()
	
	AngleX = Y
	AngleY = X
	
	On = true
	AlignOffset = false
	RunService:BindToRenderStep(Key, Enum.RenderPriority.Camera.Value - 10, Update)
end)


Tool.Unequipped:Connect(function()
	if On == false then return end
	AlignOffset = true
	UserInputService.MouseBehavior = Enum.MouseBehavior.Default
	Mouse.Icon = ""
	coroutine.wrap(function()
		wait(0.5)
		RunService:UnbindFromRenderStep(Key)
		Camera.CameraType = Enum.CameraType.Custom
		AngleX = 0
		AngleY = 0
		On = false
	end)()
end)

This should be everything that is effecting the camera currently.

*Local script in tool.

Any update? It’s been a while since I’ve heard anything.

Eurika! I’ve done it.

SavedCFrame = Camera.CFrame.Position - HumanoidRootPart.CFrame.Position

CameraCFrame = CFrame.new(SavedCFrame + HumanoidRootPart.Position)

This is what I’m using now.