I am trying to make a lock on system similar to For Honor, you lock on, face the enemy, and the camera offsets over the shoulder a little.
The issue is that when I lock onto the enemy, I clip into the ground, the camera does track them but my body clips or teleports into the ground instead of facing the enemy.
I have looked through my code and I’m quite confused, I actually restarted from the beginning multiple times, and all of my attempts resulted in a similar effect of the player clipping into the ground, this was actually my 4th attempt.
I did look through posts and a lot of tutorials on youtube, infact most of my basis is actual off of tutorials (likely the issue), I tried my best to understand how the code works, and I think I got the general idea and understand it all a bit better but I couldn’t fix the issue
I am sorry if I overlooked something really simple and don’t mean to waste anyone’s time, I tried not to post anything on the dev forum and attempt to understand how to make something like this on my own but I’ve given up and would really appreciate some help on this.
-- Services
local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local LocalPlayer = Players.LocalPlayer
-- Camera Settings
local CameraSettings = {
ViewLeft = 0,
ViewRight = 15,
ViewUp = 7,
ViewDown = 0,
ViewForwards = -25,
ViewBackwards = 0,
ViewRotationLeft = -10,
ViewRotationRight = 0,
ViewRotationUp = 0,
ViewRotationDown = 0,
ViewRotationForwards = 0,
ViewRotationBackwards = 0,
LockFieldOfView = 0,
FieldOfView = 70,
}
local LockOnRange = 20
local LockOn = false
local CurrentTarget = nil
local LastTarget = nil
-- Functions
local function getClosestEnemy()
local closestDistance = math.huge
local closestEnemy = nil
for _, obj in pairs(workspace:GetChildren()) do
if obj:IsA("Model") and obj:FindFirstChild("Humanoid") and obj:FindFirstChild("HumanoidRootPart") and obj ~= LocalPlayer.Character then
local distance = (obj.HumanoidRootPart.Position - LocalPlayer.Character.HumanoidRootPart.Position).magnitude
if distance < closestDistance and distance <= LockOnRange then
closestDistance = distance
closestEnemy = obj
end
end
end
return closestEnemy
end
local function updateLockOn()
if not LockOn or not CurrentTarget or not CurrentTarget.Parent then
LockOn = false
CurrentTarget = nil
return
end
local distanceToTarget = (CurrentTarget.HumanoidRootPart.Position - LocalPlayer.Character.HumanoidRootPart.Position).magnitude
if distanceToTarget > LockOnRange then
local closestEnemy = getClosestEnemy()
if closestEnemy then
CurrentTarget = closestEnemy
else
LockOn = false
CurrentTarget = nil
return
end
end
local lookVector = (CurrentTarget.HumanoidRootPart.Position - LocalPlayer.Character.HumanoidRootPart.Position).unit
local rotation = CFrame.new(Vector3.new(), Vector3.new(lookVector.x, 0, lookVector.z))
LocalPlayer.Character:SetPrimaryPartCFrame(CFrame.new(LocalPlayer.Character.HumanoidRootPart.Position) * rotation)
local rotationAngle = math.rad(CameraSettings.ViewRotationLeft)
local rotatedLookVector = Vector3.new(
lookVector.x * math.cos(rotationAngle) - lookVector.z * math.sin(rotationAngle),
lookVector.y,
lookVector.x * math.sin(rotationAngle) + lookVector.z * math.cos(rotationAngle)
)
local cameraOffset = Vector3.new(
CameraSettings.ViewRight,
CameraSettings.ViewUp,
CameraSettings.ViewForwards
)
local currentCFrame = workspace.CurrentCamera.CFrame
local targetCFrame = CFrame.new(
LocalPlayer.Character.HumanoidRootPart.Position + cameraOffset,
LocalPlayer.Character.HumanoidRootPart.Position + cameraOffset + rotatedLookVector
)
workspace.CurrentCamera.CFrame = currentCFrame:Lerp(targetCFrame, 0.1)
end
local function toggleLockOn()
LockOn = not LockOn
if LockOn then
CurrentTarget = getClosestEnemy()
updateLockOn()
else
CurrentTarget = nil
end
end
UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
if not gameProcessedEvent then
if input.KeyCode == Enum.KeyCode.LeftControl then
toggleLockOn()
end
end
end)
RunService.RenderStepped:Connect(function()
if LocalPlayer.Character and LocalPlayer.Character:FindFirstChild("Humanoid") then
updateLockOn()
end
end)