I need help figuring out how to orbit camera around character using mouse delta

Essentially my goal is to make the camera rotate the same way the default camera script does when a player right-clicks their mouse, but what’s happening is instead of the camera orbiting around the PrimaryPart, the camera itself is rotating in-place at the offset

This is the code so far:

local speed = 10
local offset = Vector3.new(0, 4, 8)

local userInputService = game.UserInputService

local characterAdded = game.Players.LocalPlayer.CharacterAdded
local primaryPart = characterAdded:Wait().PrimaryPart

local currentCamera = workspace.CurrentCamera

local x, y = 0, 0

local zeroVector2 = Vector2.zero
local lookAt = CFrame.lookAt
local fromOrientation = CFrame.fromEulerAnglesYXZ
local rad = math.rad

characterAdded:Connect(function(character)
	primaryPart = character.PrimaryPart
end)
characterAdded = nil

game["Run Service"]:BindToRenderStep("Camera", 1, function(deltaTime)
	local mouseDelta = userInputService:GetMouseDelta()

	if mouseDelta ~= zeroVector2 then
		x += mouseDelta.X * deltaTime * speed
		y += mouseDelta.Y * deltaTime * speed
	end

	local position = primaryPart.Position
	local cframe = lookAt(position + offset, position) * fromOrientation(-rad(y), -rad(x), 0)

	currentCamera.CFrame = cframe
	currentCamera.Focus = cframe
end)
1 Like

What I did is push the camera back with the magnitude of a variable called distance, and the direction being from the camera’s look vector to the camera’s position. For some reason it starts freaking out around the poles but you can figure that out lol (or I’ll try to fix it when I have time).


Also I didn’t really know what you wanted to do with the offsets so I just didn’t include it in the code:

local speed = 15
local offset = Vector3.new(0, 4, 8)

local userInputService = game.UserInputService

local currentCamera = workspace.CurrentCamera

local x, y = 0, 0

local zeroVector2 = Vector2.zero
local lookAt = CFrame.lookAt
local fromOrientation = CFrame.fromEulerAnglesYXZ
local rad = math.rad

local plr = game.Players.LocalPlayer
plr.CharacterAdded:Wait();

repeat wait() until plr.Character.PrimaryPart ~= nil;
local primaryPart = plr.Character.PrimaryPart

currentCamera.CameraType = Enum.CameraType.Scriptable;

local distance = 10;

game:GetService("RunService").RenderStepped:Connect(function(deltaTime)
	userInputService.MouseBehavior = Enum.MouseBehavior.LockCenter;
	local mouseDelta = userInputService:GetMouseDelta()

	if mouseDelta ~= zeroVector2 then
		x += mouseDelta.X * deltaTime * speed
		y += mouseDelta.Y * deltaTime * speed
	end

	local position = primaryPart.Position
	local camCF = currentCamera.CFrame;
	
	local cframe = CFrame.new(primaryPart.Position) * CFrame.fromAxisAngle(camCF.RightVector , -math.rad(y)) * CFrame.fromAxisAngle(Vector3.yAxis,-math.rad(x)) ;
	
	local newPos = (cframe.Position - cframe.LookVector * distance);
	
	local newCF = CFrame.lookAt(newPos, position);
	
	currentCamera.CFrame = newCF
	currentCamera.Focus = newCF
end)
1 Like

Thank you for your help! I did some experimenting myself and found out that a big part of the issues I was having was because I didn’t realise how important the order of CFrame math is. The result is as follows:

local primaryPartCFrame = CFrame.new(primaryPart.Position)

currentCamera.CFrame = primaryPartCFrame * fromOrientation(-rad(y), -rad(x), 0) * offset -- Offset is now == CFrame.new(0, 4, 8)
currentCamera.Focus = primaryPartCFrame

The above is very close to my target and doesn’t have the issues around the poles, but there’s one last finishing touch I need help to implement, which is how to make it so that the offset is angled towards the PrimaryPart (the way I tried using lookAt caused unexpected results unfortunately)

Somehow found the solution :smile:, this is the code:

local speed = 10
local offset = CFrame.new(0, 4, 8)

local userInputService = game.UserInputService

local characterAdded = game.Players.LocalPlayer.CharacterAdded
local primaryPart = characterAdded:Wait().PrimaryPart

local currentCamera = workspace.CurrentCamera

local x, y = 0, 0

local zeroVector2 = Vector2.zero
local lookAt = CFrame.lookAt
local fromOrientation = CFrame.fromEulerAnglesYXZ
local rad = math.rad

characterAdded:Connect(function(character)
	primaryPart = character.PrimaryPart
end)
characterAdded = nil

game["Run Service"]:BindToRenderStep("Camera", 1, function(deltaTime)
	local mouseDelta = userInputService:GetMouseDelta()

	if mouseDelta ~= zeroVector2 then
		x += mouseDelta.X * deltaTime * speed
		y += mouseDelta.Y * deltaTime * speed
	end

	local position = primaryPart.Position
	local cframe = CFrame.new(position) * fromOrientation(-rad(y), -rad(x), 0) * offset
	local test = lookAt(cframe.Position, position)

	currentCamera.CFrame = test
	currentCamera.Focus = CFrame.new(position)
end)
2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.