Spectate Function Bugs

Hello, this spectate function has a few bugs in it, whenever you stop spectating and try spectating again the NextPlayer function doesn’t work and the function also spectates yourself. Any help with fixing this script is appreciated.

local Players = game:GetService("Players")
local GetPlayers = Players:GetPlayers()

local Camera = game.Workspace.CurrentCamera
local Position = 1

local Spectate = script.Parent:FindFirstChild("Spectate")
local SpectateButton = script.Parent:FindFirstChild("SpectateButton")
local PlayerName = Spectate:FindFirstChild("PlayerName")
local NextPlayer = Spectate:FindFirstChild("NextPlayer")

SpectateButton.Visible = true

SpectateButton.Activated:Connect(function()
	local Humanoid = Players.LocalPlayer.Character:FindFirstChild("Humanoid")
	
	if Spectate.Visible == false then
		Spectate.Visible = true
	else
		Spectate.Visible = false
		Camera.CameraSubject = Humanoid
	end
end)

NextPlayer.Activated:Connect(function()
	local Player = Players:GetPlayers()[Position]
	local Humanoid = Player.Character:FindFirstChildOfClass("Humanoid")
	
	if Humanoid then
		Position = Position + 1
		Camera.CameraSubject = Humanoid
		PlayerName.Text = "Spectating "..Player.Name
	end
end)

Alright. You never seem to set the position back to 1 when going over the number of players there are (minus you yourself). Also, you should use table.remove() to get rid of yourself from the number of players. Lastly, when spectating you should always check whether the position is above the number of possible players.

local Players = game:GetService("Players")
local GetPlayers = Players:GetPlayers()

local Camera = game.Workspace.CurrentCamera
local Position = 1

local Spectate = script.Parent:FindFirstChild("Spectate")
local SpectateButton = script.Parent:FindFirstChild("SpectateButton")
local PlayerName = Spectate:FindFirstChild("PlayerName")
local NextPlayer = Spectate:FindFirstChild("NextPlayer")

SpectateButton.Visible = true

SpectateButton.Activated:Connect(function()
	local Humanoid = Players.LocalPlayer.Character:FindFirstChild("Humanoid")
	
	if Spectate.Visible == false then
		Spectate.Visible = true
	else
		Spectate.Visible = false
		Camera.CameraSubject = Humanoid
	end
end)

NextPlayer.Activated:Connect(function()
	local PlayerList = Players:GetPlayers()
	table.remove(PlayerList, game.Players.LocalPlayer)

	Position = Position > (#Players:GetPlayers() - 1) and 1 or Position --just an extra check

	local Player = PlayerList[Position]
	local Humanoid = Player.Character:FindFirstChildOfClass("Humanoid")
	
	if Humanoid then
		Position = Position + 1 > (#Players:GetPlayers() - 1) and 1 or Position + 1
		Camera.CameraSubject = Humanoid
		PlayerName.Text = "Spectating "..Player.Name
	end
end)
1 Like

Alright thanks for this, I’ll test it right now.

Alright so while running this new script this error is displayed in the output when you run the function.

invalid argument #2 to ‘remove’ (number expected, got Instance)

Oh, sorry, forgot to use the table.find().

local Players = game:GetService("Players")
local GetPlayers = Players:GetPlayers()

local Camera = game.Workspace.CurrentCamera
local Position = 1

local Spectate = script.Parent:FindFirstChild("Spectate")
local SpectateButton = script.Parent:FindFirstChild("SpectateButton")
local PlayerName = Spectate:FindFirstChild("PlayerName")
local NextPlayer = Spectate:FindFirstChild("NextPlayer")

SpectateButton.Visible = true

SpectateButton.Activated:Connect(function()
	local Humanoid = Players.LocalPlayer.Character:FindFirstChild("Humanoid")
	
	if Spectate.Visible == false then
		Spectate.Visible = true
	else
		Spectate.Visible = false
		Camera.CameraSubject = Humanoid
	end
end)

NextPlayer.Activated:Connect(function()
	local PlayerList = Players:GetPlayers()
	table.remove(PlayerList, table.find(PlayerList, game.Players.LocalPlayer))

	Position = Position > (#Players:GetPlayers() - 1) and 1 or Position --just an extra check

	local Player = PlayerList[Position]
	local Humanoid = Player.Character:FindFirstChildOfClass("Humanoid")
	
	if Humanoid then
		Position = Position + 1 > (#Players:GetPlayers() - 1) and 1 or Position + 1
		Camera.CameraSubject = Humanoid
		PlayerName.Text = "Spectating "..Player.Name
	end
end)

So on the humanoid variable, the output is displaying that it’s attempting to index nil with the character.

That’s weird, try printing Position and the player that is selected. This could also be caused by you testing it alone as there will be nothing in the table and PlayerList[1] would be nil.

Alright so while testing with multiple players it works, although the game is intended to be playable in single player too, is there a way I could prevent it from erroring if there is only one player?

oh yes, I believe adding a check should work.

local Players = game:GetService("Players")
local GetPlayers = Players:GetPlayers()

local Camera = game.Workspace.CurrentCamera
local Position = 1

local Spectate = script.Parent:FindFirstChild("Spectate")
local SpectateButton = script.Parent:FindFirstChild("SpectateButton")
local PlayerName = Spectate:FindFirstChild("PlayerName")
local NextPlayer = Spectate:FindFirstChild("NextPlayer")

SpectateButton.Visible = true

SpectateButton.Activated:Connect(function()
	local Humanoid = Players.LocalPlayer.Character:FindFirstChild("Humanoid")
	
	if Spectate.Visible == false then
		Spectate.Visible = true
	else
		Spectate.Visible = false
		Camera.CameraSubject = Humanoid
	end
end)

NextPlayer.Activated:Connect(function()
	if #Players:GetPlayers() == 1 then return end
	
	local PlayerList = Players:GetPlayers()
	table.remove(PlayerList, table.find(PlayerList, game.Players.LocalPlayer))

	Position = Position > (#Players:GetPlayers() - 1) and 1 or Position --just an extra check

	local Player = PlayerList[Position]
	local Humanoid = Player.Character:FindFirstChildOfClass("Humanoid")
	
	if Humanoid then
		Position = Position + 1 > (#Players:GetPlayers() - 1) and 1 or Position + 1
		Camera.CameraSubject = Humanoid
		PlayerName.Text = "Spectating "..Player.Name
	end
end)
1 Like