How would i make the camera rotate around a part?

Basically trying to get a camera to look at a part, but rotate around the part aswell.

Tried looking at Camera Manipulation but it didnt work.

So dont really know what to do / where to start here

1 Like

The code below will make your camera orbit the part, just make sure it’s in a LocalScript when you’re using it.

The offset variable determines where you want the camera to be. The X value determines left/right, the Y value determines up/down, and Z determines front/back. By default, the offset is 15 studs backward from the part.

The direction variable determines which direction you want the camera to rotate per iteration. It’s a little hard to explain which axis determines which, so I will refer to the below picture to describe it.


The X axis determines the camera’s “Roll”, the Y axis determines the camera’s “Yaw”, and Z determines “Pitch.”

I can further clarify anything if necessary.

--[[Variables]]--
--Services--
local RunService = game:GetService("RunService");

--Main--
local cam = workspace.CurrentCamera;

local part : Part = nil; --Assign a part here
local offset = Vector3.new(0, 0, 15); --Positional offset from the part. The Z axis is front and back.
offset = CFrame.new(offset);

local direction = Vector3.new(0, 3, 0); --This will be turned into a CFrame later. By default, this will be a simple horizontal rotation.

--[[Functions]]--
local cfAng = CFrame.Angles;
local rad = math.rad;

function radifyVector(vector : Vector3)
	return cfAng(rad(vector.X), rad(vector.Y), rad(vector.Z));
end

function spin()
	cam.CameraType = Enum.CameraType.Scriptable; --Makes it so we can manipulate the camera
	cam.CFrame = CFrame.new(part.Position) * offset;
	
	--OrbitingPart.CFrame = CFrame.new(PartToOrbit.Position) * CFrame.Angles(math.rad(RotStep), 0, 0)

	for i = 1, 120 do
		cam.CFrame = CFrame.new(part.Position) * radifyVector(direction * i) * offset;
		RunService.RenderStepped:Wait();
	end
end
3 Likes

Alright i think i get most of it, although the main things im not understanding are

Not entirely sure what this does but its returning some value

Probably just me, but when working with CFrames and stuff, why do we multiply and like not add or something

Is this better for the script if we abbreviate it or are we doing it just because

1 Like

My radifyVector function just turns a a Vector3, whose values are presumed to be angular measurements in degrees, and returns a CFrame.Angles value that uses radians.

I’m not really sure of the technical reason we multiply CFrames by each other; the article that tries to explain it is too much for my small brain to handle.

I abbreviate those two functions for readability and a small performance boost. I must emphasize that this performance boost isn’t noticable unless you are calling them a considerable amount of times per second.

Alright, i get it somewhat
And one more quick question
i tried having it also look at the part at a angle so in the i = loop i did

	for i = 1, 120 do
		print(3)
		Cam.CFrame = CFrame.new(LookAt.Position) * FunnyNumberThingy(Vector3.new(0,.5,0) * i) * camOffset
		Cam.CFrame = CFrame.new(Cam.CFrame.Position, LookAt.Position)
		Rs.RenderStepped:Wait()
	end
end

Mainly looking at

Cam.CFrame = CFrame.new(Cam.CFrame.Position, LookAt.Position)

Is this a good way of doing it or is there a better way i can have the camera look at the part its rotating?

4 Likes

Does it work?

Yes it does work
(Character limit)

If it ain’t broke, don’t fix it

5 Likes

Lmao :skull: Anyways thanks for the help i appreciate it

1 Like

Roblox actually has an example-script on their docs specifically on how to do this. You can find it here.

Here’s their example script:

local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
 
local target = workspace:FindFirstChild("Part")  -- The object to rotate around
local camera = workspace.CurrentCamera
camera.CameraType = Enum.CameraType.Scriptable
local rotationAngle = Instance.new("NumberValue")
local tweenComplete = false
 
local cameraOffset = Vector3.new(0, 10, 12)
local rotationTime = 15  -- Time in seconds
local rotationDegrees = 360
local rotationRepeatCount = -1  -- Use -1 for infinite repeats
local lookAtTarget = true  -- Whether the camera tilts to point directly at the target
 
local function updateCamera()
	if not target then return end
	camera.Focus = target.CFrame
	local rotatedCFrame = CFrame.Angles(0, math.rad(rotationAngle.Value), 0)
	rotatedCFrame = CFrame.new(target.Position) * rotatedCFrame
	camera.CFrame = rotatedCFrame:ToWorldSpace(CFrame.new(cameraOffset))
	if lookAtTarget == true then
		camera.CFrame = CFrame.new(camera.CFrame.Position, target.Position)
	end
end
 
-- Set up and start rotation tween
local tweenInfo = TweenInfo.new(rotationTime, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut, rotationRepeatCount)
local tween = TweenService:Create(rotationAngle, tweenInfo, {Value=rotationDegrees})
tween.Completed:Connect(function()
	tweenComplete = true
end)
tween:Play()
 
-- Update camera position while tween runs
RunService.RenderStepped:Connect(function()
	if tweenComplete == false then
		updateCamera()
	end
end)



Here’s my original response:

Here’s a common way of doing it using the RunService inside a localscript.

Name the script Camera and place it either in StarterPlayerScripts or StarterCharacterScripts.

Add a part to your workspace, this will be used as our focal point:

-- Services and References
local RunService = game:GetService("RunService")
local camera = workspace.CurrentCamera -- Current camera
local currentRot = 0 -- Variable for storing current rotation

-- Variables you can customize
local focusCFrame = workspace:FindFirstChild('Part').CFrame -- CFrame.new(0, 0, 0) or Your.Part.CFrame
local cameraOffset = CFrame.new(0, 12, 12) -- Camera Offset to part
local rotationSpeed = 6 -- How fast camera rotates

function rotateCamera(deltaTime: number)
	-- Multiply with time between each frame to compensate for FPS variation
	currentRot += rotationSpeed * deltaTime -- Add our rotationSpeed

	-- Calculate new Position
	local newPos = focusCFrame 
		* CFrame.Angles(0, math.rad(currentRot), 0) * cameraOffset

	-- Apply new position and look towards our target
	camera.CFrame = CFrame.new(newPos.Position, focusCFrame.Position)
end

-- The Magic
RunService.RenderStepped:Connect(function(deltaTime) -- Runs every "tick"
	camera.CameraType = Enum.CameraType.Scriptable -- Make camera scriptable
	
	rotateCamera(deltaTime)
end)

EDIT: Added deltaTime to the RenderStepped event; to compensate for different FPS values.

EDIT 2: Made sure camera is scriptable at all times and added reference to “Part” in workspace.

6 Likes