I’m building a Camera Controller reminiscent of the Shiftlock camera (with minor changes.) One of these mechanics reminiscent of Shiftlock is keeping the Camera focused, at all times, behind and to the right of the player, despite any rotation of the player and / or camera.
Here, you can view the problem in action. The Camera’s focus seems to shift depending on my Camera’s orientation.
Here you can find the intended result. This is simply ROBLOX’s default Shiftlock mode.
Below you can find the code relevant to this issue.
local currentCamera = workspace.CurrentCamera
local mouse = game.Players.LocalPlayer:GetMouse()
local character = game.Players.LocalPlayer.Character or game.Players.LocalPlayer.CharacterAdded:Wait()
local rootPart = character:WaitForChild("HumanoidRootPart")
local playerPosition = rootPart.Position
local standardCameraPosition = rootPart.Position + Vector3.new(5, 2.25, 0)
local standardCameraRotation = Vector2.new(0, math.rad(-60))
local standardCameraZoom = 10
local cameraPosition = standardCameraPosition
local cameraRotation = standardCameraRotation
local cameraZoom = standardCameraZoom
local cameraRotationBounds = {math.rad(-81), math.rad(20)}
local cameraZoomBounds = nil
local cameraSpeed = 0.1
local cameraRotateSpeed = 10
local cameraMouseRotateSpeed = 0.25
local function cameraModeHandler()
currentCamera.CameraType = Enum.CameraType.Scriptable
currentCamera.CameraSubject = nil
end
cameraModeHandler()
local function updateCameraProperties()
local cameraRotationCFrame = CFrame.Angles(0, cameraRotation.X, 0) * CFrame.Angles(cameraRotation.Y, 0, 0)
currentCamera.CFrame = cameraRotationCFrame + cameraPosition + cameraRotationCFrame*Vector3.new(0, 0, cameraZoom)
currentCamera.Focus = currentCamera.CFrame - Vector3.new(0, currentCamera.CFrame.p.Y, 0)
end
game:GetService("UserInputService").InputBegan:Connect(function(inputObject)
if inputObject.KeyCode == Enum.KeyCode.I then
cameraZoom = cameraZoom - 5
elseif inputObject.KeyCode == Enum.KeyCode.O then
cameraZoom = cameraZoom + 5
end
if cameraZoomBounds ~= nil then
cameraZoom = math.min(cameraZoom, cameraZoomBounds[1], cameraZoomBounds[2])
else
cameraZoom = math.max(cameraZoom, 0)
end
updateCameraProperties()
end)
mouse.Move:Connect(function()
local deltaRotation = game:GetService("UserInputService"):GetMouseDelta() * Vector2.new(-1, -1)
cameraRotation = cameraRotation + deltaRotation*math.rad(cameraMouseRotateSpeed)
end)
local function runServiceBound()
local movement = rootPart.Position - playerPosition
game:GetService("UserInputService").MouseBehavior = Enum.MouseBehavior.LockCenter
local cameraLookVector = currentCamera.CFrame.LookVector
local readFromRotation = math.atan2(-cameraLookVector.X, -cameraLookVector.Z)
rootPart.CFrame = CFrame.new(rootPart.Position) * CFrame.Angles(0, readFromRotation, 0)
cameraPosition = cameraPosition + movement
playerPosition = rootPart.Position
updateCameraProperties()
end
game:GetService("RunService"):BindToRenderStep("BoundedFunction", Enum.RenderPriority.Camera.Value-1, runServiceBound)
Specifically, the problem seems to rest in runServiceBound()
and updateCameraProperties
. The following excerpt of code (found in runServiceBound()
) is my current solution:
local cameraLookVector = currentCamera.CFrame.LookVector
local readFromRotation = math.atan2(-cameraLookVector.X, -cameraLookVector.Z)
rootPart.CFrame = CFrame.new(rootPart.Position) * CFrame.Angles(0, readFromRotation, 0)
This process achieves only a portion of what I desire, as it keeps the Character model consistently facing forwards, however the Camera fails to consistently stay behind and to the right of the Character’s model, the other half of what I need.
Any ideas?