Lock on Camera Issue

Hey guys Im having troubles with my Third Person camera and my Lock On Camera

Here are some videos

Third Person Camera:

Lock On Camera:

The Problem:

See when I switch between camera’s, the camera does not stay in the same position as it was locked in. Here is an example:

As you can see my camera doesnt stay focused on the NPC it takes the current delta of the mouse (which changes even with Mouse.LockCenter) and applies it once i switch from lock on camera to third person camera.

I’ve narrowed down the issue:
I’ve narrowed down the problem to xAngle and yAngle.
It looks like they keep updating even if the mouse is locked in a certain position.
I can’t stop them from updating because its all in a RenderStepped loop. Does anyone have any ideas how to solve this? I thought maybe writing to Mouse.Delta might work but its Read-Only?

Thanks-

Here is the script I’m working with:

local character = Player.Character or Player.CharacterAdded:wait()
local lockon = character:WaitForChild("States").LockOn

local UserInputService = game:GetService("UserInputService")



game:GetService("RunService").RenderStepped:Connect(function()
local cam = workspace.Camera

UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
cam.CameraType = Enum.CameraType.Scriptable
cam.CameraSubject = character:WaitForChild("CamPart")



end)

local playersService = game:GetService("Players")
local workspaceService = game:GetService("Workspace")
local runService = game:GetService("RunService")
local userInputService = game:GetService("UserInputService")

-- config:
local SENSITIVITY = 0.4
local WORLD_OFFSET = Vector3.new(0, 0, 0)
local LOCAL_OFFSET = Vector3.new(0, 1.75, 9.5)

-- variables:
local camera = workspaceService.CurrentCamera
local localPlayer = playersService.LocalPlayer
local xAngle = 0
local yAngle = 0


 -- main:
-- handle camera moving
userInputService.InputChanged:Connect(function(input, isProcessed)
    -- validate input
    if isProcessed then return end
    if input.UserInputType ~= Enum.UserInputType.MouseMovement then return end
    -- get delta
    local delta = input.Delta
    local deltaX = delta.X
    local deltaY = delta.Y

    -- update angles
    xAngle = xAngle - deltaX * SENSITIVITY
    yAngle = math.clamp(yAngle - deltaY * SENSITIVITY, -80, 80)


end)

userInputService.InputBegan:Connect(function(input)
	
if input.KeyCode == Enum.KeyCode.F and lockon.Value == false then
  lockon.Value = true
  userInputService.MouseIconEnabled = true


else if input.KeyCode == Enum.KeyCode.F and lockon.Value == true then
  lockon.Value = false
  userInputService.MouseIconEnabled = false
end
end
end)



character.States.LockOn.Changed:Connect(function()
	if character.States.LockOn.Value == false then
		

-- handle camera update
runService:BindToRenderStep("CameraUpdate", Enum.RenderPriority.Camera.Value, function()
    -- get necessary data
    local cameraSubject = camera.CameraSubject
    if not cameraSubject then return end
    local isLocalPlayer = false
    local subject
    local ignoredInstance
    -- check camera subject class
    if cameraSubject:IsA("Humanoid") then
        ignoredInstance = cameraSubject.Parent:WaitForChild("CamPart")
        if not ignoredInstance:IsA("Model") then return end
        subject = ignoredInstance:WaitForChild("CamPart")
        if not subject then return end
        if localPlayer.Character == ignoredInstance and cameraSubject.Health > 0 then
            isLocalPlayer = true
        end
    elseif cameraSubject:IsA("BasePart") then
        subject = cameraSubject
        ignoredInstance = cameraSubject
    else return end
    -- get positioned, world offset, and rotated cframe
    local xAngleCFrame = CFrame.Angles(0, math.rad(xAngle), 0)
    local anglesCFrame = xAngleCFrame:ToWorldSpace(CFrame.Angles(math.rad(yAngle), 0, 0))
    local cameraPosition = subject.Position + WORLD_OFFSET
     local startCFrame = CFrame.new(cameraPosition):ToWorldSpace(anglesCFrame)
    -- get camera focus and local offset cframe
    local cameraCFrame = startCFrame:ToWorldSpace(CFrame.new(LOCAL_OFFSET))
    local cameraFocus = cameraCFrame:ToWorldSpace(CFrame.new(0, 0, -LOCAL_OFFSET.Z))
    -- assign camera properties
    camera.Focus = camera.CFrame
    camera.CFrame = cameraCFrame
    camera.CFrame = cameraCFrame:ToWorldSpace(CFrame.new(0, 0, -camera:GetLargestCutoffDistance({ignoredInstance})))
    -- rotate character
    if isLocalPlayer then
        local primaryPartCFrame = ignoredInstance:GetPrimaryPartCFrame()
        local newCFrame = CFrame.new(primaryPartCFrame.Position):ToWorldSpace(xAngleCFrame)
        ignoredInstance:SetPrimaryPartCFrame(newCFrame)
    end
end)


    indent preformatted text by 4 spaces
	else if character.States.LockOn.Value == true then
		game:GetService("RunService").RenderStepped:Connect(function()
for i,v in ipairs(workspace:GetChildren())do
  local oppHRP = v:FindFirstChild("HumanoidRootPart")
  local oppHuman = v:FindFirstChild("Humanoid")
  local rootPart = character:WaitForChild("HumanoidRootPart")


  if oppHuman and oppHuman.Health > 0 and oppHRP then
    local aggro = oppHuman:FindFirstChild("Aggro")
    if (rootPart.Position - oppHRP.Position).Magnitude < 200 and character.Humanoid.Health > 0 and aggro then
      local ray = Ray.new(rootPart.Position, (oppHRP.Position - rootPart.Position).Unit * 500)
      local inSight, position = workspace:FindPartOnRayWithIgnoreList(ray,{character})

      if inSight and lockon.Value == true then
        local x = oppHRP.Position.X
        local y = oppHRP.Position.Y
        local z = oppHRP.Position.Z       

       camera.CFrame = CFrame.new(character.CamPart.Position, Vector3.new(x,y,z))
       camera.CFrame = camera.CFrame * CFrame.new(LOCAL_OFFSET )

end     
end
end
end
end)
end
end
end)
-- init
userInputService.MouseBehavior = Enum.MouseBehavior.LockCenter````
2 Likes

Of course you can!

This is why conditional statements are important.
If you want the Render Stepped to stop updating the angle values, you could try adding this if statement:

if not userInputService.MouseBehavior = Enum.MouseBehavior.LockCenter then

before the updating code so that the angles do not update while the camera is in the locked position.

1 Like

Okay i managed to get the angles to stop updating, but if you change to “Lock On” mode the camera still does that weird switch thing. Any ideas?

1 Like

You can probably use :BindToRenderStep() instead, then use :UnbindFromRenderStep() another time to stop the rendering

1 Like

But that doesnt solve the problem at all. I need to find out how to get the delta of the current position of the mouse. or something. Because it doesn’t stop the renderstep, its the fact that i need to find out how to change xAngle and yAngle to match the current position of the Camera.

2 Likes

Well yeah, then :BindToRenderStep() would be perfect, because you can make it have the same priority as the camera.

It runs the same as the camera right now, I know a bit about :BindToRenderStep() and that wouldn’t fix my problem. My problem is with the delta of the mouse because that decides the position of the camera.

1 Like