How should I create "curved tweening" for my 3D-rotating camera?

So I made a 3D-camera that rotates around the player smoothly (by tweening), kinda like in Super Mario Galaxy or -Odyssey

My problem is the tween goes from point A to point B, rather than moving in a circular fashion around the player; it behaves as if it’s a segment on a circle

(Bad motion)
image

> TweenProblem.wmv (794.4 KB) --videorecording of the problem

I heard you need to use Bezier curves, but to do that I need to calculate the point outside circle with tangents 24/7… Sounds like it can take a lot of processing power away…

(Good motion)
image

So I was wondering if there’s a better method than beziering my way out of this problem. To all you experts or people experienced with this, is Bezier really best or do I have a better alternative?

Thanks for reading! Help is appreciated

.
.
Oh yeah, here’s my cameraCode for reference (it’s not as scary as it looks)

Code
-- variables & services
local PS 		= game:GetService("Players")
local UIS 		= game:GetService("UserInputService")
local CAS 		= game:GetService("ContextActionService")
local TS 		= game:GetService("TweenService")
local RS 		= game:GetService("RunService")

local player 	= PS.LocalPlayer
local camera 	= workspace.CurrentCamera
local xAngle 	= 0
local yAngle 	= 0

-- settings
local co 		= Vector3.new(0,1,22)	--co = camera offset
local sm 		= 0.001					--sm = sensitivity multiplier




-- code body
player.CharacterAdded:Connect(function(character)
	RS.RenderStepped:Connect(function()	
		-- logistics
		if camera.CameraType ~= Enum.CameraType.Scriptable or UIS.MouseBehavior ~= Enum.MouseBehavior.LockCenter or UIS.MouseIconEnabled ~= false then
			camera.CameraType = Enum.CameraType.Scriptable
			UIS.MouseBehavior = Enum.MouseBehavior.LockCenter
			UIS.MouseIconEnabled = false
		end
		
		-- mouseinput tracking
		UIS.InputChanged:Connect(function(input)
			if input.UserInputType == Enum.UserInputType.MouseMovement then
				xAngle = xAngle - input.Delta.X * sm
				yAngle = math.clamp(yAngle - input.Delta.Y * sm,-80,80) --math.clamp so y-axis won't glitch
			end
		end)

		-- camera angles and tween
		local hrp = character:WaitForChild("HumanoidRootPart")
		local startCFrame = CFrame.new((hrp.Position)) * CFrame.Angles(0,math.rad(xAngle),0) * CFrame.Angles(math.rad(yAngle),0,0)
		local cameraCFrame = startCFrame:ToWorldSpace(CFrame.new(co.X, co.Y, co.Z))
		local cameraFocus = startCFrame:ToWorldSpace(CFrame.new(co.X, co.Y, -10000))
		
		local ti = TweenInfo.new(0.5,Enum.EasingStyle.Circular,Enum.EasingDirection.Out,0,false,0)	-- ti is tweeninfo
		local tg = {CFrame = CFrame.new(cameraCFrame.Position,cameraFocus.Position)}				-- tg is tweengoal
		local tween = TS:Create(camera,ti,tg)
		tween:Play()
	end)
end)

It does not “take a lot of processing power away,” don’t worry! Your computer does millions of computations every second. Don’t underestimate its power!!!

Here is a desmos page I just spent half an hour making for you. I tried to leave all my work so you can get a full understanding of what I did.

Under the assumption that the old and new position are always on the circle, you can easily find their tangents by using the “negative reciprocal” of the slope from the center of the circle to the point on the circle. Then you can just do some simple algebra to solve for the intersections of both lines after doing that.

Though… I don’t think you need any of this. You should just be able to interpolate the angle from point 2 to point 1; or vice versa.

3 Likes

My way of doing this is just creating an invisible part in the humanoidrootpart of the player then tween its orientation then make a function that fires everytime the orientation of the part changes, then set the camera CFrame on the parts lookvector + its position and make it look on the part

kinda late reply lol

You could always just use ellipses and then map the domain to be -pi, pi then convert that to a value from 0 to 1 then lerp that. I have a math library which does all the hard stuff for u thou