So I’ve been trying to script a lock on target system (a character and a camera looking at the Target) and everything seems to work but there’s only one issue that I can’t solve. Basically whenever I go forward, It goes a bit to the left and the closer I am to the target, the faster I go to the left.
I also realised that if I put 0 at X-axis of CAMERA_OFFSET then it doesn’t happens but I don’t want to have X-axis at 0 but 12. Here’s the script:
local UIS = game:GetService('UserInputService')
local RS = game:GetService('RunService')
local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local HMRP = Character:WaitForChild('HumanoidRootPart')
local HUM = Character:WaitForChild('Humanoid')
local Mouse = Player:GetMouse()
local Camera = workspace.CurrentCamera
local Target
local MOUSE_HITBOX = Vector3.new(3,3,3)
local CAMERA_OFFSET = Vector3.new(12,2,12)
local CAMERA_LERP = .25
function unLock()
Target = nil
HUM.AutoRotate = true
Camera.CameraType = Enum.CameraType.Custom
script.Target.Value = nil
end
function check(p)
return p:FindFirstChild('HumanoidRootPart') and p:FindFirstChild('Humanoid') and p.Humanoid.Health > 0
end
UIS.InputBegan:Connect(function(k,e)
if(e)then return end
k = k.KeyCode ~= Enum.KeyCode.Unknown and k.KeyCode or k.UserInputType
if(k == Enum.KeyCode.L or k == Enum.UserInputType.MouseButton3)then
if(Target)then
unLock()
return
end
local Hit = workspace:GetPartBoundsInBox(CFrame.new(Mouse.Hit.Position), MOUSE_HITBOX)
for i,v in pairs(Hit) do
local p = v.Parent
if(check(p))then
Target = p
script.Target.Value = p
Camera.CameraType = Enum.CameraType.Scriptable
end
end
end
end)
RS.RenderStepped:Connect(function()
if(Target)then
if not(check(Target)) then
unLock()
return
end
local HMRP2 = Target.HumanoidRootPart.CFrame
local distance = Player:DistanceFromCharacter(Target.HumanoidRootPart.Position)
print(distance)
HUM.AutoRotate = false
HMRP.CFrame = CFrame.lookAt(HMRP.Position, Vector3.new(HMRP2.Position.X, HMRP.Position.Y, HMRP2.Position.Z))
Camera.CFrame = Camera.CFrame:Lerp(CFrame.lookAt((CFrame.lookAt(HMRP.Position, Target.HumanoidRootPart.Position) * CFrame.new(CAMERA_OFFSET)).Position, Target.HumanoidRootPart.Position), CAMERA_LERP)
end
end)
That happens because of Roblox’s movement code, the only possbile way (the hard way) i can think of its to make own controller that moves character relative to his rotation
You could try locking from a center point w/o locking their rotation out the get-go to allow for more free movement. If a mouse lock type thing is required, it will still work properly p sure… You can find some UE5 tutorials on this and just take the concept from them as well.
not a completely own, but at least when Locked On the target.
Could use humanoid:MoveTo(Direction)
you can get direction using character.HumanoidRootPart.CFrame.LookVector or character.HumanoidRootPart.CFrame.RightVector
and multiply it by speed you want
You’d basically treat the character’s head as the central point focused on by the camera and then get the unit vector towards the target RootPart’s position. You may be able to do Target:GetPivot() but I’m pretty sure roblox made it so the pivot points of characters are at the bottom. Some pseudo code:
local RunService = game:GetService("RunService")
local Camera = workspace.CurrentCamera
Camera.CameraType = Enum.CameraType.Scriptable
local characterHead = myCharacterHead
local targetRootPart = myTargetsRootPart
RunService.RenderStepped:Connect(function()
local headPos = characterHead.Position
local targetPos = targetRootPart.Position
local camOffset = (Camera.CFrame.Position-headPos).Magnitude -- don't need this if u do a set offset...
Camera.CFrame = CFrame.lookAt(headPos,targetPos)*CFrame.new(0,0,camOffset)
end)
pretty sure this will work, didn’t test this just an fyi
So it sorta worked but now when i change x axis of camera offset, the camera isnt really looking at the target anymore but a bit on the right as my x axis goes. Is there any way to make the camera also looking at the target after the offset is changed?
If you still want an offset on the x-axis you could probably do something like this:
local RunService = game:GetService("RunService")
local Camera = workspace.CurrentCamera
Camera.CameraType = Enum.CameraType.Scriptable
local characterHead = myCharacterHead
local targetRootPart = myTargetsRootPart
RunService.RenderStepped:Connect(function()
local headPos = characterHead.Position
local targetPos = targetRootPart.Position
local offsetX = Camera.CFrame.RightVector*2 -- account for the offset prior to the lookat...
Camera.CFrame = CFrame.lookAt(headPos+offsetX,targetPos)*CFrame.new(0,0,30)
end)
The problem is, I’m pretty sure you’ll run into the same issue you’ve had… but you never know unless you try tbh.
Roblox control scripts makes the character go to where the camera is looking, when you point your camera backwards your character will turn and walk toward that direction, your lock on changes the camera CFrame and the control script keeps making it go towards where the camera is looking due to some offsets or some stuff.
How to fix
First we need to fork the control script, press play on studio and clone the PlayerModule inside the PlayerScripts:
Stop testing, and place it at StarterPlayerScripts:
Open ControlModule under PlayerModule, thats the module we have to edit in order to fix the issue.
Firstly, we need to tell the module when we are locked on to someone, and what the root part is:
Here i add some simple variables and functions for the variables we will use, then the function we have to edit is calculateRawMoveVector:
We then can simply add an if statement to change the variable it uses to the one we want, that being the root part:
In short, what is needed to do is fork the script, change the function that calculates move direction, and make it calculate by your Root Part CFrame instead, since in your Lock on script you move the root part to look directly to the opponent, we can use it and it will always move directly to it when you move forward, “fixing” the bug.