Camera Coding (Setting the offset)

Hey guys, I’m writing a piece of code that’s supposed to feel like shift lock, but let the player still have full range of motion (turning, etc.) Basically, I want the camera to always be on the right of the player. It’ll look like this:

But stay on the right when he turns around like this

I’m mathematically challenged, so hopefully one of you guys could give me a formula to figure this out. Currently, I’ve been having troubles when it comes to turning the camera or player onto another axis.

Here’s what I have so far:

hum = script.Parent:WaitForChild("Humanoid")

rs = game:GetService("RunService")

Head = script.Parent:WaitForChild("Head")

rs.RenderStepped:connect(function()
	
	--wait()
	
	local Cam = game.Workspace.CurrentCamera
	
	hum.CameraOffset = Vector3.new(2*Head.CFrame.lookVector.X*Cam.CFrame.lookVector.X, 0, 2*Head.CFrame.lookVector.Z--[[*Cam.CFrame.lookVector.Z]])
	--hum.CameraOffset.Z = 2*Head.CFrame.lookVector.Z
	
end)

Could anyone tell me what I’m doing wrong?

If it helps, the camera system is supposed to act like GTA or Watchdogs. It’s a localscript in the starter character.

15 Likes

I just wrote this up here, no testing, so it might not work.

local RunService = game:GetService("RunService")
local Player = game.Players.LocalPlayer
local Camera = game.Workspace.CurrentCamera
local y = 0 -- Y rotation of camera (left and right)
local x = 0 -- X rotation of camera (up and down)

local FLAT_OFFSET_VECTOR = Vector3.new(3,1,8) -- Displacement from HumanoidRootPart, doesn't move up or down when you change y rotation
local OFFSET_VECTOR = Vector3.new(0,1,4) -- Displacement from HumanoidRootPart, but does move up and down

RunService:BindToRenderStep("CameraMove",Enum.RenderPriority.Camera.Value-1,function()
    if not (Player.Character and Player.Character:FindFirstChild("HumanoidRootPart")) then return end -- Only run if the HumanoidRootPart can be found
    
    local root = Player.Character.HumanoidRootPart -- Part to rotate around
    Camera.CFrame = CFrame.new(root.Position) * CFrame.Angles(0,y,0) * CFrame.new(FLAT_OFFSET_VECTOR) * CFrame.Angles(x,0,0) * CFrame.new(OFFSET_VECTOR)
end)

Just change the x and y angles to rotate the camera. This will need a scriptable camera to work properly.

4 Likes

Not exactly what I was after - but I appreciate the contribution. What I was after is the camera system like in GTA or Watchdogs, where the player is slightly to the left, but still has a full range of motion. Watch how the character moves in this video:

Versus this gif of Shiftlock:

https://gyazo.com/416f22a452d25f7a9b9d8e8085369a74.gif

Pretty much the same thing, except for the player is always facing the cursor in shift lock. I don’t want him to follow the cursor in shift lock, but the only problem is that the humanoid’s offset turns with the player.

I want the player to be able to face the camera, and be offset to the right, while also being offset to the right when he’s facing left, forward, and right.

If that doesn’t make sense let me know, I’ll elaborate a little more.

Note: Your code made the camera basically lock behind the player, and not rotate. This might be useful in the future, but it’s not quite what I was looking for :stuck_out_tongue: Thanks anyways though!

Yeah the script I put doesn’t actually cause the character to follow the camera, what might be the problem is the default roblox core movement scripts move relative to the character, so if you are holding W and turning the camera, the character will turn as well.

I just tested and can confirm that the character doesn’t move at all when the camera rotates.

Camera turning continuously:

https://gyazo.com/941bd4805f2e0d0dc5d04defdd34a84d

Mouse controls:

https://gyazo.com/c6073a4f5eb4305dd61b9470e111c15d

If you don’t like how it turns or the offset, you can easily change that.

Just a quick edit to add controls:

local RunService = game:GetService("RunService")
local InputService = game:GetService("UserInputService")
local Player = game.Players.LocalPlayer
local Camera = game.Workspace.CurrentCamera
local y = 0 -- Y rotation of camera (left and right)
local x = 0 -- X rotation of camera (up and down)

local FLAT_OFFSET_VECTOR = Vector3.new(0,0,2) -- Displacement from HumanoidRootPart, doesn't move up or down when you change y rotation
local OFFSET_VECTOR = Vector3.new(2,2,10) -- Displacement from HumanoidRootPart, but does move up and down

wait(1)

InputService.InputChanged:connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseMovement then
		x = x - input.Delta.Y * 0.001
		y = y - input.Delta.X * 0.001
	end
end)

Camera.CameraType = Enum.CameraType.Scriptable

InputService.MouseBehavior = Enum.MouseBehavior.LockCenter

RunService:BindToRenderStep("CameraMove",Enum.RenderPriority.Camera.Value-1,function()
	if not (Player.Character and Player.Character:FindFirstChild("HumanoidRootPart")) then return end -- Only run if the HumanoidRootPart can be found
    
    local root = Player.Character.HumanoidRootPart -- Part to rotate around
    Camera.CFrame = CFrame.new(root.Position) * CFrame.Angles(0,y,0) * CFrame.new(FLAT_OFFSET_VECTOR) * CFrame.Angles(x,0,0) * CFrame.new(OFFSET_VECTOR)
end)
3 Likes

Camera manipulation is my expertise. This is exactly what you want:

-------------
--- INDEX ---
-------------

--Services
local userInputService = game:GetService("UserInputService")
local runService = game:GetService("RunService")

--Player & Character
local localPlayer = game:GetService("Players").LocalPlayer

--Other
local Camera = game:GetService("Workspace").CurrentCamera

--------------
--- VALUES ---
--------------

local xAngle = 0
local yAngle = 0
local cameraPos = Vector3.new(3.5,0,7.5)

----------------------
--- INITIALIZATION ---
----------------------

wait(1)
Camera.CameraType = Enum.CameraType.Scriptable
userInputService.MouseBehavior = Enum.MouseBehavior.LockCenter

-----------------
--- FUNCTIONS ---
-----------------

userInputService.InputChanged:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseMovement then
		xAngle = xAngle-input.Delta.x*0.4
		--Clamp the vertical axis so it doesn't go upside down or glitch.
		yAngle = math.clamp(yAngle-input.Delta.y*0.4,-80,80)
	end
end)

runService.RenderStepped:Connect(function()
	local Character = localPlayer.Character
	local rootPart = Character:FindFirstChild("HumanoidRootPart")
	if Character and rootPart then
		--Set rotated start cframe inside head
		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)
		
		--Set camera focus and cframe
		local cameraCFrame = startCFrame + startCFrame:vectorToWorldSpace(Vector3.new(cameraPos.X,cameraPos.Y,cameraPos.Z))
		local cameraFocus = startCFrame + startCFrame:vectorToWorldSpace(Vector3.new(cameraPos.X,cameraPos.Y,-50000))
		
		Camera.CFrame = CFrame.new(cameraCFrame.p,cameraFocus.p)
	end
end)

This script is made to work inside StarterPlayerScripts, but you can also put it in PlayerGui or StarterPack.

84 Likes

You guys both hit the nail on the head! Thanks for the help!

10 Likes

hey quick question, is there any way to adapt this to the joystick for a controller? i tried doing it myself but i dont fully understand how the XAngle and the YAngle part of the code works and how it translates the mouse to move the camera.

1 Like