I want to make something like the Orbital CameraType using a custom script for finer control. Here’s what I have so far, but it is not quite smooth/accurate because RenderStepped is independent of InputChanged. Does anyone have an idea how to script a camera that orbits an object while allowing smooth left/right control of the orbit position?
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local Camera = workspace.CurrentCamera
local X, Y, Z = 0, 5, 0
workspace:WaitForChild("Map")
UserInputService.InputChanged:Connect(function(Input)
X = 15*math.sinh(Input.Position.X)
Z = 15*math.cosh(Input.Position.Y)
end)
RunService.RenderStepped:Connect(function()
print(X,Y,Z)
Camera.CFrame = CFrame.lookAt(Vector3.new(workspace.Map.GolfBall.Position.X+X, workspace.Map.GolfBall.Position.Y+Y, workspace.Map.GolfBall.Position.Z+Z), workspace.Map.GolfBall.Position)
end)
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local Camera = workspace.CurrentCamera
Camera.CameraSubject = workspace.Part --The part you want to orbit around
local CameraAngle = 0
local function SetCameraAngle() --You don't have to pass in your part's position through CameraSubject, but I think it's convenient
Camera.CFrame = CFrame.new(workspace.CurrentCamera.CameraSubject.Position) * CFrame.Angles(0,CameraAngle,0) * CFrame.new(0,5,7):ToWorldSpace(CFrame.Angles(math.rad(-30),0,0))
end
RunService:BindToRenderStep("CustomOrbitalCamera", Enum.RenderPriority.Camera.Value, SetCameraAngle)
local BeganConnection
local ChangedConnection
local EndedConnection
BeganConnection = UserInputService.InputBegan:Connect(function()
local FormerTime = os.clock()
RunService:UnbindFromRenderStep("CameraPan")
if ChangedConnection then ChangedConnection:Disconnect() end
if EndedConnection then EndedConnection:Disconnect() end
local AngleVelocity = 0
ChangedConnection = UserInputService.InputChanged:Connect(function(Input)
local CurrentTime = os.clock()
local AngleDelta = math.atan2(Input.Position.Y - Camera.ViewportSize.Y / 2, Input.Position.X - Camera.ViewportSize.X / 2) - math.atan2(Input.Position.Y - Camera.ViewportSize.Y / 2 - Input.Delta.Y, Input.Position.X - Camera.ViewportSize.X / 2 - Input.Delta.X)
CameraAngle = (CameraAngle + AngleDelta) % (math.pi * 2)
AngleVelocity = (AngleDelta) / (CurrentTime - FormerTime)
if AngleVelocity > 0 then AngleVelocity = math.min(13, AngleVelocity) end --maximum angular velocity to decelerate from, in radians. The velocity isn't 100% accurate and can be too fast, like hundreds of radians per second
if AngleVelocity < 0 then AngleVelocity = math.max(-13, AngleVelocity) end
FormerTime = os.clock()
end)
EndedConnection = UserInputService.InputEnded:Connect(function(Input)
local function CameraPan(TimeDelta)
AngleVelocity /= 1.05 --increase to make camera decelerate faster
local AngleDelta = AngleVelocity * TimeDelta
if -0.001745 < AngleDelta and AngleDelta < 0.001745 then --smallest rotational increment before stopping, in radians
AngleVelocity = 0
RunService:UnbindFromRenderStep("CameraPan")
end
CameraAngle = (CameraAngle + AngleDelta) % (math.pi * 2)
end
RunService:BindToRenderStep("CameraPan", Enum.RenderPriority.Camera.Value, CameraPan)
end)
end)