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````