Game breaks if player joins during a cutscene

I want to stop the game from breaking when a player joins during a cutscene.

If a player joins during a cutscene, everything stops & the cutscene plays forever.

I looked for solutions on the Developer Hub but I didn’t find anything that solves my problem.

I have different maps for different amounts of players in my game, because the maps for 20 players need to be bigger than the maps for 1 player.

I have 2 remote events (called cameraInterpolateEvent & cameraToPlayerEvent) in ReplicatedStorage in a folder called ‘Remotes’.

Here is my game script in ServerScriptService (simplified):

local RAINBOW = game.ReplicatedStorage:WaitForChild("RainbowMap")
local CONTROL = game.ReplicatedStorage:WaitForChild("ControllerMap")
local VOLCANO = game.ReplicatedStorage:WaitForChild("VolcanoMap")
local BURGER = game.ReplicatedStorage:WaitForChild("BurgerMap")

local cameraInterpolateEvent = game.ReplicatedStorage.Remotes.cameraInterpolateEvent
local cameraToPlayerEvent = game.ReplicatedStorage.Remotes.cameraToPlayerEvent

-------------------------------------------------------------------------------

function teleportPlayers(partCFrame)
	
end

function intermissionTimer()
	
end

function gameTimer()
	
end

function inGame()
	math.randomseed(os.time())
	if #game:GetService("Players"):GetPlayers() == 1 then -- If there is 1 player in the game then

		local EasyMaps = math.random(1, 2) -- Pick a random number (no lower than 1, no higher than 2)
		
	if EasyMaps == 1 then -- If the number selected is 1 then
		CONTROL:Clone().Parent = game.Workspace -- A controller map will appear in Workspace
		cameraInterpolateEvent:FireAllClients(game.Workspace.CameraGroup9.CameraPart.CFrame, game.Workspace.CameraGroup9.TargetPart.CFrame,1) -- A cutscene will play
		wait(2) -- for 2 seconds
		teleportPlayers() -- The player will be teleported to the selected map
		wait(0.2)
		cameraToPlayerEvent:FireAllClients() -- The cutscene will end
		gameTimer() -- The game will last for a certain amount of time.
			
		elseif EasyMaps == 2 then -- If the number selected is 2 then
		RAINBOW:Clone().Parent = game.Workspace -- A rainbow map will appear in Workspace
		cameraInterpolateEvent:FireAllClients(game.Workspace.CameraGroup15.CameraPart.CFrame, game.Workspace.CameraGroup15.TargetPart.CFrame,1) -- A cutscene will play
		wait(2) -- for 2 seconds
		teleportPlayers() -- The player will be teleported to the selected map
		wait(0.1)
		cameraToPlayerEvent:FireAllClients() -- The cutscene will end
		gameTimer() -- The game will last for a certain amount of time.
		end
		
	elseif #game:GetService("Players"):GetPlayers() > 1 then -- If there's more than 1 player in the game then

		local MediumMaps = math.random(1, 3) -- Pick a random number (no lower than 1, no higher than 3)
		
		if MediumMaps == 1 then -- If the number selected is 1 then
			VOLCANO:Clone().Parent = game.Workspace -- A volcano map will appear in Workspace
			cameraInterpolateEvent:FireAllClients(game.Workspace.CameraGroup3.CameraPart.CFrame, game.Workspace.CameraGroup3.TargetPart.CFrame,1) -- A cutscene will play
			wait(2) -- for 2 seconds
			teleportPlayers() -- The player will be teleported to the selected map
			wait(1)
			cameraToPlayerEvent:FireAllClients() -- The cutscene will end
			gameTimer() -- The game will last for a certain amount of time.
			
		elseif MediumMaps == 2 then -- If the number selected is 2 then...
			RAINBOW:Clone().Parent = game.Workspace -- I think you see the pattern now.
			cameraInterpolateEvent:FireAllClients(game.Workspace.CameraGroup15.CameraPart.CFrame, game.Workspace.CameraGroup15.TargetPart.CFrame,1)
			wait(2)
			teleportPlayers()
			wait(1)
			cameraToPlayerEvent:FireAllClients()
			gameTimer()
			
		elseif MediumMaps == 3 then
			BURGER:Clone().Parent = game.Workspace
			cameraInterpolateEvent:FireAllClients(game.Workspace.CameraGroup4.CameraPart.CFrame, game.Workspace.CameraGroup4.TargetPart.CFrame,1)
			wait(2)
			teleportPlayers()
			wait(1)
			cameraToPlayerEvent:FireAllClients()
			gameTimer()
		end
	end
end

function intermission() -- Play intermission
	Map:Destroy() -- Destroy the map
	wait(1)
	intermissionTimer() -- Wait 30 seconds for a new game to start
end

function SPLEEF() -- The game
	intermission()
	inGame()
end

repeat -- Repeat
	SPLEEF() -- the game
until -- until
2+2==5 -- two plus two is equal to five (Never stops repeating because 2+2 will never be equal to 5)

Here is the cutscene script in StarterCharacterScripts:

local getplayer = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local player = game.Players.LocalPlayer
local PlayerGui = player:FindFirstChild("PlayerGui")
local cameraInterpolateEvent = game.ReplicatedStorage.Remotes.cameraInterpolateEvent
local cameraToPlayerEvent = game.ReplicatedStorage.Remotes.cameraToPlayerEvent

cameraInterpolateEvent.OnClientEvent:Connect(function(posEnd,focusEnd,duration)
	if not player:FindFirstChild("AbsolutelyNothing") then
		local camera = game.Workspace.CurrentCamera
		camera.CameraType = Enum.CameraType.Scriptable
		
		camera:Interpolate(
			posEnd,
			focusEnd,
			duration
		)
	end
end)

cameraToPlayerEvent.OnClientEvent:Connect(function()
	local camera = game.Workspace.CurrentCamera
	
	camera:Interpolate(
		player.Character.PrimaryPart.CFrame,
		player.Character.PrimaryPart.CFrame,
		1
	)
	wait(.7)
	camera.CameraType = Enum.CameraType.Custom
	
end)

If anyone could help me fix this, that would be awesome! If you have any questions then feel free to ask, thanks to anyone who considers helping! :slightly_smiling_face:

This is a fix of your code and an optimization.

First off, for games with map-based systems, you should add a module script to store the map data so it’s easier to access:
image

In the module script, paste this inside:

local Maps = {
	["EasyMapsInfo"] = {
		["Map1"] = {
			"CONTROL",
			"CameraGroup9"
		},
		
		["Map2"] = {
			"RAINBOW",
			"CameraGroup15"
		}
	},
	
	["MediumMapsInfo"] = {
		["Map1"] = {
			"VOLCANO",
			"CameraGroup3"
		},
		
		["Map2"] = {
			"RAINBOW",
			"CameraGroup15"
		},
		
		["Map3"] = {
			"BURGER",
			"CameraGroup4"
		}
	}
}

return Maps

You should also rename your maps in replicated storage so that they match the names listed here (CONTROL, RAINBOW, VOLCANO, RAINBOW).

Switch out the server script with this:

--//Services
local Players = game:GetService("Players")
local ServerScriptService = game:GetService("ServerScriptService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

--//Requires
local Maps = require(ServerScriptService.Maps)

--//Variables
local cameraInterpolateEvent = ReplicatedStorage.Remotes.cameraInterpolateEvent
local cameraToPlayerEvent = ReplicatedStorage.Remotes.cameraToPlayerEvent

--//Functions
function teleportPlayers(partCFrame)

end

function intermissionTimer()

end

function gameTimer()

end

function inGame()
	math.randomseed(os.time())
	
	if #Players:GetPlayers() == 1 then 	
		--//Picks a map
		local MapInfo = Maps.EasyMapsInfo["Map" .. math.random(1, 2)]
		
		--//Puts it into workspace
		local Map = ReplicatedStorage:FindFirstChild(MapInfo[1]):Clone()
		Map.Name = "Map"
		Map.Parent = workspace
		
		--//Cutscene begins
		local CameraGroup = workspace:FindFirstChild(MapInfo[2])
		cameraInterpolateEvent:FireAllClients(CameraGroup.CameraPart.CFrame, CameraGroup.TargetPart.CFrame,1) 
		
		task.wait(2) 
		
		teleportPlayers() 
		
		task.wait(0.2)
		
		cameraToPlayerEvent:FireAllClients() 
		gameTimer() 

	elseif #Players:GetPlayers() > 1 then
		--//Picks a map
		local MapInfo = Maps.MediumMapsInfo["Map" .. math.random(1, 3)]
		
		--//Puts it into workspace
		local Map = ReplicatedStorage:FindFirstChild(MapInfo[1]):Clone()
		Map.Name = "Map"
		Map.Parent = workspace
		
		--//Cutscene begins
		local CameraGroup = workspace:FindFirstChild(MapInfo[2])
		cameraInterpolateEvent:FireAllClients(CameraGroup.CameraPart.CFrame, CameraGroup.TargetPart.CFrame,1) 

		task.wait(2) 

		teleportPlayers() 

		task.wait(0.2)

		cameraToPlayerEvent:FireAllClients() 
		gameTimer() 
	end
end

function intermission() 
	workspace.Map:Destroy() 
	
	task.wait(1)
	
	intermissionTimer() 
end

function SPLEEF()
	intermission()
	
	inGame()
end

while true do
	SPLEEF()
end

Switch out the local script with this:

--//Services
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")

--//Variables
local LocalPlayer = Players.LocalPlayer
local CurrentCamera = workspace.CurrentCamera

local cameraInterpolateEvent = ReplicatedStorage.Remotes.cameraInterpolateEvent
local cameraToPlayerEvent = ReplicatedStorage.Remotes.cameraToPlayerEvent

--//Functions
cameraInterpolateEvent.OnClientEvent:Connect(function(posEnd,focusEnd,duration)
	if not LocalPlayer:FindFirstChild("AbsolutelyNothing") then
		CurrentCamera.CameraType = Enum.CameraType.Scriptable

		CurrentCamera:Interpolate(
			posEnd,
			focusEnd,
			duration
		)
	end
end)

cameraToPlayerEvent.OnClientEvent:Connect(function()
	CurrentCamera:Interpolate(
		LocalPlayer.Character.PrimaryPart.CFrame,
		LocalPlayer.Character.PrimaryPart.CFrame,
		1
	)
	
	task.wait(.7)
	CurrentCamera.CameraType = Enum.CameraType.Custom
end)

Here’s some advice though:

  1. For comments, you should be more general and not put one in every line since it gets confusing and too much info is given.

  2. Organization of your script is important so that it’s more readable to you and others.

Also, I suspect that the game breaks because the SPLEEF function is in a constant loop. You should call it when the server opens and when the round ends.

3 Likes

Hi Katrist,

I’m sorry that it was hard to read, I can see how. I will make my next post less flooded with information.

You solved my problem & made my scripts much easier to work with &, from now on, I shall organise my scripts better to help save time.

I’ve never understood Module scripts until now; your scripts helped me understand how they work. I am so grateful that such an experienced scripter replied to me.

Thank you so much!

1 Like