What shift lock does is basically lock the mouse in the center of the screen, and move the camera a bit.
I’ve seen people messing with the Camera module.
This seems like a bit of a “tricky solution” for me.
I would just Use RunService.PreRender or RunServer.RenderStepped (Deprecated), UserInputService.MouseBehaviour, and Humanoid.CameraOffset.
For the rotation I use BodyGyro on the HumanoidRootPart.
Example:
--Local script in StarterPlayerCharacter
local plr = game:GetService("Players").LocalPlayer
local mouse = plr:GetMouse()
local char = script.Parent
local hum = char:WaitForChild("Humanoid")
local rotation = Instance.new("BodyGyro") --Create a new body gyro.
rotation.P = 1000000 --Increase the power
rotation.Parent = hum.RootPart --Parent it to the humanoid
local conn -- connection variable
function shiftLock(active) --Toggle shift.lock function
if active then
hum.CameraOffset = Vector3.new(1,0.5,0) -- I assume this is about the right camera offset.
rotation.MaxTorque = Vector3.new(0, math.huge, 0) --Max the power on the Y axis
conn = game:GetService("RunService").RenderStepped:Connect(function()
rotation.CFrame = mouse.Origin
game:GetService("UserInputService").MouseBehavior = Enum.MouseBehavior.LockCenter
end) --Set the mouse to center every frame.
else
hum.CameraOffset = Vector3.new(0,0,0) --Move the camera back to normal.
rotation.MaxTorque = Vector3.new(0, 0, 0) --Clear the power on the HumanoidRootPart
if conn then conn:Disconnect() end -- Allow mouse to move freely.
end
end
hum.Died:Connect(function()
shiftLock(false) --Stop connection on player death
end)
shiftLock(true) -- Toggle shift lock
wait(10)
shiftLock(false) -- Will disconnect
For some reason, PreRender didn’t work for me although RenderStepped did? Not sure why.
Testing:
I’ve used your code. I also open a new file with your code in case any other script was interfering with it. The mouse is locked as you can see in this video
Here’s a file that has the problem shiftlock.rbxl (145.1 KB)
Did you grab the actual player module or did you copy and paste the function into a player module?
I think you meant “and” here. Yes I’ve grabbed the player module while the game was running and copy pasted the function over the previous update function
Also put shiftLock under StarterPlayerScripts
I’ve written local shiftLockOn = game.StarterPlayer.shiftlock, so i don’t think it’s necessary to do that.
local uis = game:GetService("UserInputService")
local rs = game:GetService("RunService")
rs.RenderStepped:Connect(function()
uis.MouseBehavior = Enum.MouseBehavior.LockCenter--lock mouse to center, pretty self explanatory
game.Players.LocalPlayer.Character.Humanoid.CameraOffset=Vector3.new(2,0,0)--offsetting the camera
end)
Some might ask why the script above needed to be renderStepped, the playerModule constantly changes these values.
local cam = workspace.CurrentCamera
local plr = game:GetService("Players").LocalPlayer
game:GetService("RunService"):BindToRenderStep("hmm",199, function()--this is because of sync issues
if plr.Character then
local rootPart = plr.Character:WaitForChild("HumanoidRootPart")
if rootPart then
rootPart = plr.Character:WaitForChild("HumanoidRootPart")
rootPart.CFrame = CFrame.new(rootPart.CFrame.p, rootPart.CFrame.p + Vector3.new(cam.CFrame.LookVector.X,0,cam.CFrame.LookVector.Z))
end
end
end)
Yep, especially with the zoom. There’s no easy way to perfectly manipulate the zoom unless you mess around with the ever changing cameraModule or you make your own camera script, which requires you to fiddle around with bindToRenderStep priority values as it desyncs everything running in RenderStepped. I think enough attempts has been taken for the first one in this thread. For the latter one here’s a code from the video if anyone’s interested. No need to offset humanoid camera if you’re using this.
-- LOCALS --
-- Services
local uis = game:GetService("UserInputService")
local rs = game:GetService("RunService")
local context = game:GetService("ContextActionService")
-- Player & Character
local plr = game:GetService("Players").LocalPlayer
-- Other
local Camera = game:GetService("Workspace").CurrentCamera
local mouse = plr:GetMouse()
local cameraDB = false
local zoomDB = false
-- Values
local xAngle = 0
local yAngle = 0
local cameraPos = Vector3.new(2,0,8.5)
-- CAMERA SETTING --
wait(0.01)
Camera.CameraType = Enum.CameraType.Scriptable
-- FUNCTIONS --
context:BindAction("CameraMovement", function(_,_,input)
xAngle = xAngle - input.Delta.x*0.4
yAngle = math.clamp(yAngle - input.Delta.y*0.4,-80,80)
end, false, Enum.UserInputType.MouseMovement)
rs.RenderStepped:Connect(function()--use bindToRenderStepped instead with appropriate priority values
local c = plr.Character or plr.CharacterAdded:Wait()
local rootPart = c:FindFirstChild("HumanoidRootPart")
if c and rootPart then
local startCFrame = CFrame.new((rootPart.CFrame.p + Vector3.new(0,2,0)))*CFrame.Angles(0, math.rad(xAngle), 0)*CFrame.Angles(math.rad(yAngle), 0, 0)
local cameraCFrame = startCFrame + startCFrame:VectorToWorldSpace(Vector3.new(cameraPos.X,cameraPos.Y,cameraPos.Z))--the value you'd want to change
local cameraFocus = startCFrame + startCFrame:VectorToWorldSpace(Vector3.new(cameraPos.X,cameraPos.Y,-50000))
Camera.CFrame = CFrame.new(cameraCFrame.p,cameraFocus.p)
end
end)
Seems like the body rotation is updating slower than the camera update. I faced this too. Whatever is doing the body rotation, if you put it in ** BindToRenderStep(“something”,199, function() enter code here end), it would’ve fixed it.
I made another post about this and did that. The main issue I found was that you have to set humanoid.AutoRotate to false, and then manually turn the character by setting the CFrame with a lerp. It is still fairly glitchy with these two methods combined, but it only happens when you rotate, no longer when you jump or in free fall, and with a turn lerp it’s barely noticeable since the character isn’t locked where the camera is facing.
Edit: Here’s the code that I use. It works well but if you think you can fully rid the glitch then feel free to optimize it:
humanoid.AutoRotate = false
runService:BindToRenderStep("Before camera", 199, function()
local currentTime = tick()
if camera.CameraType == Enum.CameraType.Follow and humanoid.MoveDirection.Magnitude > 0 and humanoid.WalkSpeed > 0 then
local swayX = math.cos(currentTime * 15) * 0.3
local swayY = math.abs(math.sin(currentTime * 15) * 0.3)
local sway = Vector3.new(swayX + 3.5, swayY, 1)
humanoid.CameraOffset = humanoid.CameraOffset:lerp(sway, 0.25)
elseif camera.CameraType ~= Enum.CameraType.Follow or humanoid.MoveDirection.Magnitude == 0 or humanoid.WalkSpeed == 0 then
local offsetStandard = Vector3.new(3.5, 0, 1)
humanoid.CameraOffset = humanoid.CameraOffset:Lerp(offsetStandard, 0.25)
end
local goalCFrame = CFrame.new(rootPart.Position, rootPart.Position + Vector3.new(camera.CFrame.LookVector.X, 0 , camera.CFrame.LookVector.Z))
rootPart.CFrame = rootPart.CFrame:Lerp(goalCFrame, 0.5)
end)
I might be wrong here, but lerping isn’t instant right? Even when you set the lerp with smallest possible time, its still supposed to be slower (hence laggier) than directly setting the CFrame of hrp. rootPart.CFrame = CFrame.new(rootPart.CFrame.p, rootPart.CFrame.p + Vector3.new(cam.CFrame.LookVector.X,0,cam.CFrame.LookVector.Z))
It depends on what you want though, you could do this if you want exactly like shift lock. However if you want slower character rotations, lerping would be the way to go. Idk if changing bindToRenderStep priorities would help in that case. Might have to open up a new thread for that.
I think I didn’t articulate myself correctly. I like the lerp because the slight, organic delay of you turning and your character turning helps prevent the character glitching from being obvious. The character has yet to stop glitching entirely but it’s whatever.
Hey, I’ve tried the script out and it works great! However, I am unable to disable the shiftlock again. I’ve tried setting them to trues and false’s. None of the combination is working, do you have any idea how I could do it?