I am currently attempting to create a lock-on targeting system for my game, the third person camera is fairly basic but works. I am currently attempting to create a “coherent” lock-on system, and for the most part it works, I just have a couple of quirks I need help solving. One of these quirks is when the player walks close to the dummy the camera bugs out, especially if they jump on them. Another quirk is attempting to transition from lock-on to normal third person camera, currently I just basically record the X and Y axis of the lookat CFrame and so when it is disabled, the camera will “start” at that angle. The issue is, it seems the lock-on is slightly lower and to the left offset-wise compared to my third person camera system, even though they are using the same vector variable for offset, this causes a small jump when toggling the lock-on system.
One small fix to the first issue of the camera bugging out as you get closer or jump on the dummy was to basically put a min (and max) magnitude, this somewhat solves the issue, but can look janky as players can still move the third-person camera when they reach that threshold, then it just instantly locks on as they leave. This also makes the second issue more visible, bc it “transitions” from lockon camera angles to the third-person camera one.
Not really a bug issue, but It would also be nice to get some pointers on how to implement focus_offset, so it doesnt have to be the center of the rootpart.
Another fix I tried with the lock-on not being the exact angle was to basically use the X and Y axis angles I “record” and use it instead, but the lock-on is now less consistent (the mouse is no longer at the center of the root part, and is at some “random” spot on the dummy).
Footage of the issues. The video maybe too low quality to see the issue relating to toggling on and off the lock-on, and as such I also include the place file, this is exactly “one-to-one” the code I am using in the video. This actual “issue” is inside the module script inside of replicatedstorage.
Place file, open module inside replicated storage:
DevelopmentSmallThings.rbxl (104.9 KB)
The “relavent” code.
local itpmod={
enabled=false,
focus=nil :: BasePart?,
angles={
current=Vector2.zero,
min=Vector2.new(-math.huge,-75),
max=Vector2.new(math.huge,75),
},
sensitivity=Vector2.new(1,.4),
focus_offset=Vector3.new(2,2,8),
offset=Vector3.new(2,2,8),
}
local imod={
enabled=false,
}
RunService:BindToRenderStep("CamController",Enum.RenderPriority.Camera.Value+1,function(delta:number)
if not imod.enabled then return end
if itpmod.enabled then
repeat
local character=LOCALPLAYER.Character
if not character then break end
local rootpart=character:FindFirstChild("HumanoidRootPart") :: BasePart?
if not rootpart or not rootpart:IsA("BasePart") then break end
if itpmod.auto_rotate then rootpart.CFrame=CFrame.new(rootpart.Position)*CFrame.fromEulerAnglesYXZ(0,math.rad(itpmod.angles.current.X),0) end
CAMERA.CameraType=Enum.CameraType.Scriptable
UserInputService.MouseBehavior=Enum.MouseBehavior.LockCenter
if itpmod.focus==nil then
CAMERA.CFrame=CFrame.new(rootpart.Position)*CFrame.fromEulerAnglesYXZ(math.rad(itpmod.angles.current.Y),math.rad(itpmod.angles.current.X),0)*CFrame.new(itpmod.offset)
else
local finalVector=local finalVector=CFrame.lookAt(CFrame.lookAt(rootpart.Position,itpmod.focus.Position)*CFrame.new(itpmod.offset).Position,itpmod.focus.CFrame:PointToWorldSpace(itpmod.focus_offset))
local lookAtVector=Vector3.new(finalVector:ToEulerAnglesYXZ())
itpmod.angles.current=Vector2.new(math.clamp(math.deg(lookAtVector.Y),itpmod.angles.min.X,itpmod.angles.max.X),math.clamp(math.deg(lookAtVector.X),itpmod.angles.min.Y,itpmod.angles.max.Y))
--UserInputService.MouseBehavior=Enum.MouseBehavior.Default
CAMERA.CFrame=finalVector
end
CAMERA.Focus=rootpart.CFrame--CFrame.new(rootpart.CFrame:PointToWorldSpace(Vector3.new(itpmod.offset.X,itpmod.offset.Y,0)))*rootpart.CFrame.Rotation
if itpmod.popper.enabled then CAMERA.CFrame=calculate_popper(rootpart.CFrame:PointToWorldSpace(Vector3.new(itpmod.offset.X,itpmod.offset.Y,0)),itpmod.popper.ignore_list) end
until true
if itpmod.last_input~=nil then apply_camera_rot("CamController",itpmod.last_input.UserInputState,itpmod.last_input) end
end
end)