How to tween the camera CFrame in a RunService loop?

hello
so recently I’ve realised I’m really bad at manipulating cameras. in this case, I can’t tween the camera without it acting weirdly. There are 2 camera modes I have currently (each room will only have 1 camera mode):

  • Follow: Statically attached to the HRP of the player and will move with the player (won’t rotate, however)
  • Fixed: Fixed into a specified location, but will rotate to look at the player.

I would like it so that when you change room (and thus the camera mode), it will tween to that position instead of instantly teleporting there. When I tried, it sort of just fell apart and didn’t position the camera correctly…

local Zone = require(game:GetService("ReplicatedStorage").Modules.Zone)
local rs = game:GetService("RunService")
local ts = game:GetService("TweenService")
local twinfo = TweenInfo.new(0.4, Enum.EasingStyle.Quint, Enum.EasingDirection.InOut)

local player = game:GetService("Players").LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local cam = game:GetService("Workspace").CurrentCamera
local hum = char:WaitForChild("Humanoid")
local rooms = game:GetService("Workspace").Rooms

local plrcamtype = "Follow"
local plrroom = nil
local goal = nil

-- mouse to cam
local mouse = player:GetMouse()
local maxtilt = 5


repeat
	task.wait()
	cam.CameraType = Enum.CameraType.Scriptable
until
cam.CameraType == Enum.CameraType.Scriptable

-- customise camera for the follow camtype

-- camera position is as follows:
-- Vector3.new(left/right, up/down, forwards/backwards)

local campos = Vector3.new(0, 20, 6)

-- camera tilt is as follows:
-- CFrame.fromEulerAnglesXYZ(math.rad(uptilt/downtilt), math.rad(lefttilt/righttilt), math.rad(tilt))

local camrot = CFrame.fromEulerAnglesXYZ(math.rad(-65), math.rad(0), math.rad(0))

-- checking cameratypes

for i, v in rooms:GetChildren() do
	local roomzone = Zone.new(v)
	roomzone.localPlayerEntered:Connect(function()
		plrcamtype = v:GetAttribute("CamType")
		plrroom = v
	end)
end

-- main loop

rs:BindToRenderStep("LockCamera", 201, function()
	
	-- mouse to cam
	
	local mousecf = CFrame.Angles(
		math.rad((((mouse.Y - mouse.ViewSizeY / 2) / mouse.ViewSizeY)) * -maxtilt),
		math.rad((((mouse.X - mouse.ViewSizeX / 2) / mouse.ViewSizeX)) * -maxtilt),
		0
	)
	
	local hrp = char:WaitForChild("HumanoidRootPart")
	if plrcamtype == "Follow" then 
		cam.CFrame = CFrame.new(hrp.Position + campos) * camrot * mousecf
		
		
	elseif plrcamtype == "Fixed" then
		cam.CFrame = CFrame.lookAt(plrroom.CamPart.Position, hrp.Position) * mousecf
	end	
	end
)

Any help would be greatly appreciated, i suck at everything to do with cameras, cframes and tweening :confused:

any help would be greatly appreciated. although it looks like a lot of code, its because I space my code out a lot for readability. it’s also a relatively simple problem to resolve, but I suck at this :\

any help…? much needed…

This text will be blurred

could still use some help, this is somewhat important to me.
I fixed up the code a little bit, so now it tweens properly.
However, the problem now is that if you continue to move, the tween will not update and will go to the previous position. Here’s the code as it is right now:

local Zone = require(game:GetService("ReplicatedStorage").Modules.Zone)
local rs = game:GetService("RunService")
local ts = game:GetService("TweenService")
local twinfo = TweenInfo.new(0.4, Enum.EasingStyle.Quint, Enum.EasingDirection.InOut)

local player = game:GetService("Players").LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local cam = game:GetService("Workspace").CurrentCamera
local hum = char:WaitForChild("Humanoid")
local hrp = char:WaitForChild("HumanoidRootPart")
local rooms = game:GetService("Workspace").Rooms

local plrcamtype = "Follow"
local plrroom = nil
local tweening = false

-- mouse to cam
local mouse = player:GetMouse()
local maxtilt = 5



repeat
	task.wait()
	cam.CameraType = Enum.CameraType.Scriptable
until
cam.CameraType == Enum.CameraType.Scriptable

-- customise camera for the follow camtype

-- camera position is as follows:
-- Vector3.new(left/right, up/down, forwards/backwards)

local campos = Vector3.new(0, 20, 6)

-- camera tilt is as follows:
-- CFrame.fromEulerAnglesXYZ(math.rad(up/down), math.rad(left/right), math.rad(tilt))

local camrot = CFrame.fromEulerAnglesXYZ(math.rad(-65), math.rad(0), math.rad(0))

-- checking cameratypes

for i, v in rooms:GetChildren() do
	local roomzone = Zone.new(v)
	roomzone.localPlayerEntered:Connect(function()
		plrcamtype = v:GetAttribute("CamType")
		plrroom = v
		
		if plrcamtype == "Follow" then
			tweening = true
			local goal = {CFrame = CFrame.new(hrp.Position + campos) * camrot}
			local camtween = ts:Create(cam, twinfo, goal)
			camtween:Play() 
			camtween.Completed:Wait()
			tweening = false
		elseif plrcamtype == "Fixed" then
			tweening = true
			local goal = {CFrame = CFrame.lookAt(plrroom.CamPart.Position, hrp.Position)}
			local camtween = ts:Create(cam, twinfo, goal)
			camtween:Play() 
			camtween.Completed:Wait()
			tweening = false
		end
	end)
end

-- main loop

rs:BindToRenderStep("LockCamera", 201, function()
	
	-- mouse to cam
	
	local mousecf = CFrame.Angles(
		math.rad((((mouse.Y - mouse.ViewSizeY / 2) / mouse.ViewSizeY)) * -maxtilt),
		math.rad((((mouse.X - mouse.ViewSizeX / 2) / mouse.ViewSizeX)) * -maxtilt),
		0
	)
	
	if plrcamtype == "Follow" then 
		--local goal = {CFrame = CFrame.new(hrp.Position + campos) * camrot}
		--local camtween = ts:Create(cam, twinfo, goal):Play()
		if not tweening then
			cam.CFrame = CFrame.new(hrp.Position + campos) * camrot * mousecf
		end
		
		
	elseif plrcamtype == "Fixed" then
		--local goal = {CFrame = CFrame.lookAt(plrroom.CamPart.Position, hrp.Position)}
		--local camtween = ts:Create(cam, twinfo, goal):Play()
		if not tweening then
			cam.CFrame = CFrame.lookAt(plrroom.CamPart.Position, hrp.Position) * mousecf
		end
	end
	
	end
)

You can’t update a tween that’s already playing, but you can instead tween it again which will override the previous tween if you’re changing the same value, or both will play at the same time if you’re changing two different values. Or at least that’s how it should be from my experience

Indeed, but I’m struggling to see where I could incorporate that into my code. Last time I tried doing that, it ended up not placing the camera in the right CFrames, which means I messed up with my implementation. Could you help me with where I replay the tween?

I’m a bit confused, but what you want is for the camera to tween to the perspective positions {CFrame = CFrame.lookAt(plrroom.CamPart.Position, hrp.Position)} and {CFrame = CFrame.new(hrp.Position + campos) * camrot} when switching between cameras? But when you switch camera types it would instantly teleport your camera. What I’m understanding is that instead of it teleporting you want a smooth transition to where it should be, relative to where it previously was?

Yes! Sorry, I wasn’t clear enough, my bad entirely.

You’ll want to tween your camera before changing your CameraType, to perfect this you’ll want to tween the Camera while it’s in Scriptable CameraType, which you should yield then switch the CameraType. The problem here is mouse and/or player might move while the tween is happening, still giving a teleporting look, so to solve this we’ll over-ride the previous tween with a new one until they’ve synced close enough then switch types, working on a demo for an example

I’m confused…
the Follow and Fixed camera methods that I’m using are not the camera types provided by roblox - they are custom and explained at the start of the message

Fixed, I used interpolation instead of tweening because tweening sucks.

local Zone = require(game:GetService("ReplicatedStorage").Modules.Zone)
local rs = game:GetService("RunService")
local ts = game:GetService("TweenService")
local twinfo = TweenInfo.new(0.4, Enum.EasingStyle.Quint, Enum.EasingDirection.InOut)

local player = game:GetService("Players").LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local cam = game:GetService("Workspace").CurrentCamera
local hum = char:WaitForChild("Humanoid")
local hrp = char:WaitForChild("HumanoidRootPart")
local rooms = game:GetService("Workspace").Rooms

local plrcamtype = "Follow"
local plrroom = nil
local tweening = false

-- mouse to cam
local mouse = player:GetMouse()
local maxtilt = 5



repeat
	task.wait()
	cam.CameraType = Enum.CameraType.Scriptable
until
cam.CameraType == Enum.CameraType.Scriptable

-- customise camera for the follow camtype

-- camera position is as follows:
-- Vector3.new(left/right, up/down, forwards/backwards)

local campos = Vector3.new(0, 20, 6)

-- camera tilt is as follows:
-- CFrame.fromEulerAnglesXYZ(math.rad(up/down), math.rad(left/right), math.rad(tilt))

local camrot = CFrame.fromEulerAnglesXYZ(math.rad(-65), math.rad(0), math.rad(0))

-- checking cameratypes

for i, v in rooms:GetChildren() do
	local roomzone = Zone.new(v)
	roomzone.localPlayerEntered:Connect(function()
		plrcamtype = v:GetAttribute("CamType")
		plrroom = v
		
	end)
end

-- main loop

rs:BindToRenderStep("LockCamera", 201, function()
	
	-- mouse to cam
	
	local mousecf = CFrame.Angles(
		math.rad((((mouse.Y - mouse.ViewSizeY / 2) / mouse.ViewSizeY)) * -maxtilt),
		math.rad((((mouse.X - mouse.ViewSizeX / 2) / mouse.ViewSizeX)) * -maxtilt),
		0
	)
	
	if plrcamtype == "Follow" then 
		cam.CFrame = cam.CFrame:Lerp((CFrame.new(hrp.Position + campos) * camrot * mousecf), 0.05)
		
		
	elseif plrcamtype == "Fixed" then
		cam.CFrame = cam.CFrame:Lerp((CFrame.lookAt(plrroom.CamPart.Position, hrp.Position) * mousecf), 0.05)
		
	end
	
	end
)

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