Custom Camera Lock Problem (Over-The-Shoulder Camera)

Hello guys, I’m new here.

so when I’m testing this Over-The-Shoulder Camera thing,

it always feel kind of buggy or laggy,

anyone know the reason?

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

local Players : Players = game:GetService("Players")
local Player : Player = Players.LocalPlayer
local Character : HumanoidDescription = Player.Character or Player.CharacterAdded:Wait()
local Humanoid : Humanoid = Character:WaitForChild("Humanoid")
local HumanoidRootPart : Part = Character:WaitForChild("HumanoidRootPart")

local Camera : Camera = game.Workspace.CurrentCamera

function CameraControl:EnterOTS()
	local function CameraLookAt()
		local CameraPos : Vector3 = Camera.CFrame.Position
		local CameraDir : Vector3 = Camera.CFrame.LookVector
		
		local MaxDistance : number = 100
		
		return CameraPos + (CameraDir * MaxDistance) :: Vector3
	end
	
	RunService:BindToRenderStep("HumanoidRootPartLookAt", Enum.RenderPriority.Camera.Value + 1, function()
		local CameraLookAtPos = CameraLookAt()
		local HumanoidRootPartLookAtPos = Vector3.new(CameraLookAtPos.X, HumanoidRootPart.Position.Y, CameraLookAtPos.Z)
		HumanoidRootPart.CFrame = CFrame.lookAt(HumanoidRootPart.Position, HumanoidRootPartLookAtPos)
	end)
end
1 Like

Sorry, the information I provided earlier was incomplete.
I don’t really think i should call it a “Over-The-Shoulder Camera” since it’s not only on top of the shoulder.
And also the code I provided is just a part in my module, the module works great but the problem is it makes the “Character” looks glitchy and not the Camera.
This comment should be a more complete information.

1 Like

You’re directly setting HumanoidRootPart.CFrame every render step, which can fight against the Humanoid’s own rotation and replication. That usually causes jitter or a laggy feeling.

If your goal is to make the character face the camera, try disabling Humanoid.AutoRotate while in OTS mode and rotate the character using a smoother approach (or use Model:PivotTo if appropriate). Also make sure you’re not competing with Roblox’s default camera or character controller.

Also, RenderPriority.Camera + 1 runs after the camera updates, but directly overriding the root part’s CFrame every frame is still likely to cause visible jitter, especially while the Humanoid is moving.

2 Likes

Thank you for the reply!

Unfortunately I need to rest now,
I’ll try what you said when I finished the rest.

Appreciate it.

2 Likes

I’m back from rest earlier, and I found my code was incomplete, again.

There should be something like Humanoid.CameraOffset = Vector3.new(2, 0, 0), but since the code was built in TweenService and its not necessary so I didn’t put in the post, sincerely apologize for it.

And I’ve tried your suggestions earlier, things went better it but came out with another problem.

-- services and usefull stuffs

function CameraControl:EnterOTS()
	Humanoid.AutoRotate = false
	
	local NewInfo = TweenInfo.new(
		0.25, Enum.EasingStyle.Back, Enum.EasingDirection.Out
	)
	local Goal = {
		CameraOffset = Vector3.new(2, 0, 0)
	}
	local CameraTween = TweenService:Create(
		Humanoid, NewInfo, Goal
	)
	CameraTween:Play()
	
	local function CameraLookAt()
		local CameraPos : Vector3 = Camera.CFrame.Position
		local CameraDir : Vector3 = Camera.CFrame.LookVector
		
		local MaxDistance : number = 100
		
		return CameraPos + (CameraDir * MaxDistance) :: Vector3
	end
	
	RunService:BindToRenderStep("HumanoidRootPartLookAt", Enum.RenderPriority.First.Value + 1, function()
		local CameraLookAtPos = CameraLookAt()
		local HumanoidRootPartLookAtPos = Vector3.new(CameraLookAtPos.X, HumanoidRootPart.Position.Y, CameraLookAtPos.Z)
		HumanoidRootPart:PivotTo(CFrame.lookAt(HumanoidRootPart.Position, HumanoidRootPartLookAtPos))
	end)
end

Here’s more completed and updated code.

The code works, and character moving didn’t cause jitter effect, but the problem is when the character is rotating it cause the character to be glitchy.

1 Like

You’re directly setting HumanoidRootPart.CFrame every frame, which is likely fighting against the Humanoid’s own rotation. Try disabling Humanoid.AutoRotate while in OTS mode and avoid overriding the root part’s CFrame every render step. Are you also using the default camera controller?

1 Like

I’ve set the

Humanoid.AutoRotate

to false in the first first line of function.

And the module is made by myself, I’m not using default camera module, or if you mean the

Camera.CameraType

then it’s still a no, I didn’t change it either.

In addition, the module works great so I think the problem came out of the OTS mode itself.

If AutoRotate is already disabled and you’re not using the default camera, then I don’t think that’s the issue anymore.

My guess is that the jitter comes from forcing the root part’s transform every render step. HumanoidRootPart:PivotTo(CFrame.lookAt(...)) continuously overwrites the character’s orientation while the Humanoid is also updating movement internally.

As a test, try only updating the character’s yaw instead of using CFrame.lookAt, or interpolate the rotation (Lerp) instead of snapping to the camera direction every frame.

Also, does the glitch only happen while the character is moving, or even when standing still and rotating the camera?

1 Like

This value means nothing btw
Idk why people still get ragebaited into writing it

It just tells id of enum and nothing else

You need to write your own PlayerModule if you want serious camera manipulation

Also for god sake please dont declear methods especially when you dont need self argument

1 Like

Ahh… I apologize for my ignorance.

I think I’ll be moving on to learn more before i finish this.

Thank you for the reply, really appreciate it.

Sorry for the late reply, and I think I’ll stop working on this temporarily.

Thank you for the help and reply in this time, I really appreciate it.

You should try directly adding the camera’s LookVector to the root’s position instead

local rootPos = HumanoidRootPart.Position
local cameraLV = Camera.CFrame.LookVector
local HumanoidRootPartLookAtPos = rootPos + Vector3.new(cameraLV.X, 0, cameraLV.Z)
HumanoidRootPart:PivotTo(CFrame.lookAt(rootPos, HumanoidRootPartLookAtPos))

I’ve always used this formula and it has always worked flawlessly. Keep AutoRotate to false though otherwise the character will still jitter. If this still doesn’t work you could always try using an AlignOrientation, though that will interpolate rather than instantly snap the root’s CFrame to the look direction