How do you return the Intro CurrentCamera to the Player's camera by pressing a button?

Hello! I’m new to the Developer Forum, so this is my first topic.
I know the basics of scripting, but I do not understand complex ones.

  1. What do you want to achieve?
  • So, I tried using ChatGPT for roblox scripting, and I was asking it to make a cinematic intro whenever the local player joins into the game.
  • The main aspect did work, the CurrentCamera teleported to certain areas, showcasing the map whilst the menu start screen was visible, and moving from one position to the other. But I wanna make it so whenever you press the play button, the CurrentCamera should return to the default player following camera. Therefore the player won’t be stuck on the menu, nor the CurrentCamera.
  1. What is the issue?
    However, ChatGPT struggled to make the Play Button stop the whole cinematic camera movement loop, and return it to the local player’s camera. I tried a lot of attempts but none worked, since I have no strong scripting knowledge.
    This is how things look in the explorer (just incase):

  2. What solutions have you tried so far?
    Not much, I couldn’t find any. And ChatGPT struggles to do large complex ones so it kept messing it up and making it worse. The solution seems very simple, I just don’t know what it is.

Here’s the LocalScript (IntroCinematic) inside of StarterPlayerScripts:

local camera = game.Workspace.CurrentCamera
local player = game.Players.LocalPlayer
local starterGui = game:GetService("StarterGui")
local playButton = game.StarterGui.StartScreen.RandomFrame.Play
local debounce = false

-- Define the list of camera positions, orientations, and speeds for the cinematic
local cameraInfo = {
	{position = Vector3.new(-111.086, 87.413, -118.91), lookAt = Vector3.new(-45.165, 87.413, 364.618), speed = 100},
	{position = Vector3.new(-585.882, 120.878, 290.307), lookAt = Vector3.new(-776.856, 120.787, -503.379), speed = 150},
	{position = Vector3.new(158.075, 120.546, -528.272), lookAt = Vector3.new(611.28, 120.822, -11.763), speed = 300},
	{position = Vector3.new(488.812, 120.772, 620.441), lookAt = Vector3.new(502.664, 120.772, 579.402), speed = 20},
}

local currentCameraIndex = 1
local isCinematicActive = false

local function startCinematicLoop()
	if debounce or isCinematicActive then return end
	debounce = true

	-- Disable default player controls
	local character = player.Character or player.CharacterAdded:Wait()
	local humanoid = character:WaitForChild("Humanoid")
	humanoid.PlatformStand = true

	isCinematicActive = true
	while true do
		-- Get the current camera info
		local currentPosition = cameraInfo[currentCameraIndex].position
		local currentLookAt = cameraInfo[currentCameraIndex].lookAt
		local speed = cameraInfo[currentCameraIndex].speed

		-- Set initial camera properties
		camera.CameraType = Enum.CameraType.Scriptable
		camera.CFrame = CFrame.new(currentPosition, currentLookAt)

		-- Calculate the direction and distance to move
		local direction = (currentLookAt - currentPosition).unit
		local distance = (currentLookAt - currentPosition).magnitude

		-- Calculate the time needed to reach the next position based on speed
		local timeToReach = distance / speed

		-- Smoothly interpolate camera position and orientation over time
		local startTime = tick()
		local currentTime = 0

		while currentTime < timeToReach do
			local alpha = currentTime / timeToReach
			local newPosition = currentPosition + direction * speed * alpha
			camera.CFrame = CFrame.new(newPosition, currentLookAt)
			currentTime = tick() - startTime
			wait()
		end

		-- Move to the next camera position
		currentCameraIndex = currentCameraIndex % #cameraInfo + 1
		isCinematicActive = false
	end
end

local function endCinematicLoop()
	debounce = false

	-- Enable default player controls
	local character = player.Character or player.CharacterAdded:Wait()
	local humanoid = character:WaitForChild("Humanoid")
	humanoid.PlatformStand = false

	-- Show GUI for ending cinematic
	starterGui:SetCore("GuiEnabled", {
		PlayerList = true,
		Backpack = true,
		Chat = true,
		All = true,
	})
end

playButton.MouseButton1Click:Connect(function()
	endCinematicLoop()
end)

player.CharacterAdded:Connect(function()
	startCinematicLoop()
end)

I would have to get the play button like this:

playButton = game.StarterGui.StartScreen.RandomFrame.Play

Any help would be much appreciated! I’m slowly learning, so explaining things simply would be helpful. If possible, make it clear what steps I need to do to fix this issue in certain parts of the LocalCcript.

1 Like

Firstly dont use chatgpt especially to learn you’re just slowing urself down.
As to why: it overcomplicates stuff, and works inefficently. its using a loop for frames instead of tweening.

To set the camera back to a player you just do this:

local Camera = workspace.CurrentCamera
Camera.CameraType = Enum.CameraType.Custom
local plr = game.Players.LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()	
if char and char:FindFirstChild("Humanoid") then
	Camera.CameraSubject = char.Humanoid
end		
2 Likes

Right off the bat, use .Activated instead of .MouseButton1Click - it registers all types of button clicks, whether on mobile/PC/Console

@zbav beat me to it but he’s right, just set the CameraType & CameraSubject and it’ll reset it for you. The only problem there is that it’ll be instantaneous, meaning there is no tween from the current camera’s position to the default head camera position. An easy way to combat this problem is to simply fade in a black cinematic screen before you set those settings, set the camera properties, and then fade out the screen

You might also wanna look into:

  • Tweens (as opposed to setting up custom interpolation, which is what you’re currently doing) - it’ll be much simpler & much easier
  • RunService - this’ll help you avoid using while loops & help setup easy connections which you can disconnect at any time without yielding (I always try to avoid using while loops, personal preference might also be a factor but generally better to use RunService)
2 Likes

Yeah, I agree. I was using ChatGPT before I was able to post topics here. It can be helpful in simple scripts or adjustments but it will keep ruining it overtime.

Thanks for the help though! This looks like it should work, so I’ll test it out when I’ve go the time…

1 Like

I’m not entirely sure where or how to structure the main script with these modifications. I’m not good at scripting. So can I get some details of how this should be put together for it to work?

And for extra detail of what I want to achieve, this is how things look in my testing place:

As you can see, the CurrentCamera just keeps on going, and doesn’t return to the player when the play button is clicked

you have some weird blur too you might wanna disable

local function endCinematicLoop()
	debounce = false

	-- Enable default player controls
	local character = player.Character or player.CharacterAdded:Wait()
	local humanoid = character:WaitForChild("Humanoid")
	humanoid.PlatformStand = false

	-- Set player camera back to normal
	if character and humanoid then
		camera.CameraType = Enum.CameraType.Custom
		camera.CameraSubject = character.Humanoid
	end	

	-- Disable lighting blur
	local Blur = game.Lighting:FindFirstChild(" Whatever the blur is called ")
	Blur.Enabled = false

	-- Show GUI for ending cinematic
	starterGui:SetCore("GuiEnabled", {
		PlayerList = true,
		Backpack = true,
		Chat = true,
		All = true,
	})
end```
1 Like

The blur animation is intended

The blur animation is there to kinda look like a black fading out screen. You press the play button, and the blur size goes from 30 to 0 in a script. And then you can see your character sharp and clear inside of the lobby.

well you can edit it as such but that should put ur camera back to ur character. make sure to hit mark as solution if it worked

1 Like

Your replies look very helpful for how to return the camera back to the player, however I still can’t figure out how to actually modify the script for it to work. Idk how to set up the script so the button should work correctly.

If anything I will try rewriting the script over and over again until it works…

I’ve already tried putting those lines of code in where they would need to be, but there’s still no function because it’s set up badly

If for some reason you do not want to use RunService to easily call Disconnect() or UnbindFromRenderStep, you can call the startCinematicLoop as it’s own thread and use task.cancel later on.

local cinematicLoopThread: thread? = nil

player.CharacterAdded:Connect(function(): ()
	cinematicLoopThread = task.spawn(startCinematicLoop)
end)

-- in your endCinematicLoop function
if cinematicLoopThread ~= nil then
	task.cancel(cinematicLoopThread)
	cinematicLoopThread = nil
end
1 Like