Help on Spectating System

In my game players can use this spectating GUI to flit between players on the team currently alive:
image
Whenever I click any of the arrows, even with players, it doesn’t do anything.
Code if needed:

function spectateGui(plr)
	local spectateGui : ScreenGui = plr:WaitForChild("PlayerGui"):WaitForChild("Spectate")
	spectateGui.Enabled = true
	
	local leftArrow = spectateGui.Spectate.SpectatePrevious
	local rightArrow = spectateGui.Spectate.SpectateNext
	
	workspace.CurrentCamera.CameraType = Enum.CameraType.Scriptable
	workspace.CurrentCamera.CameraSubject = workspace.Rig.Humanoid
	
	local spectators = {}
	
	for _, plr in ipairs(PS:GetPlayers()) do
		if plr.Team == teams.players then
			table.insert(spectators, plr)
			print(plr)
		end
		
		if #spectators == 0 then
			table.insert(spectators, workspace.Rig)
		end
	end
	
	local currentIndex = 1
	
	leftArrow.MouseButton1Click:Connect(function()
		currentIndex = currentIndex + 1
		--[[if currentIndex > #spectators then
			currentIndex = 1
		end--]]

		if spectators[currentIndex] --[[and spectators[currentIndex].Character--]] then
			workspace.CurrentCamera.CameraSubject = spectators[currentIndex].Character:FindFirstChild("Humanoid")
		end
	end)
	
	rightArrow.MouseButton1Click:Connect(function()
		currentIndex = currentIndex + 1
		if currentIndex > #spectators then
			currentIndex = 1
		end

		if spectators[currentIndex] and spectators[currentIndex].Character then
			workspace.CurrentCamera.CameraSubject = spectators[currentIndex].Character:FindFirstChild("Humanoid")
		end
	end)
end```

I am 100% sure this is not the full script, could you provide the full script so we can find the bug?

it’s hard to say why exactly it doesn’t work without seeing the output (and as @VonsRevenges said, we’d need to see the full script), but i did notice a few issues that could be causing you problems:

for starters, it’s possible that the LocalPlayer is being added to the spectators table, which would cause workspace.Rig to not be added to it (#spectators isn’t 0). if the rig was being added to it, the CameraSubject lines would throw an error, which would be something along the lines of “Character is not a valid member of Rig”. also, your if statement for “if #spectators == 0” is inside of the for loop, i’d recommend moving it to after the loop finishes.

also, since you’re initializing currentIndex at 1, and then immediately increasing it when the button is clicked, the line if spectators[currentIndex] ... would be indexing spectators[2], which would be nil if you were solo (or if the table only had workspace.Rig in it). also side note, both the left and right arrows are increasing the index, causing both buttons to have the exact same behavior

i’m not entirely sure why it’s doing nothing with other players in the game, so i’d recommend adding prints to every event connection and if statement, and seeing what the output looks like so that you know exactly what line isn’t doing what you want.

Sorry for the delay, and here is the full script with some corrections I made:

local RPS = game:GetService("ReplicatedStorage")
local SS = game:GetService("ServerStorage")
local TS = game:GetService("Teams")
local PS = game:GetService("Players")

local events = RPS.Events
local roundStatus = events.RoundStatus

local pathfinding = require(RPS.Modules.Enemies.Pathfinding)
local spawn = require(RPS.Modules.Enemies.Spawn)
local waves = require(RPS.Modules.Enemies.Waves)

local teams = {
	players = TS.players,
	spectators = TS.spectators
}

local playersAlive = {}

local rounds = {}

function spectateGui(plr)
	local spectateGui : ScreenGui = plr:WaitForChild("PlayerGui"):WaitForChild("Spectate")
	spectateGui.Enabled = true
	
	local leftArrow = spectateGui.Spectate.SpectatePrevious
	local rightArrow = spectateGui.Spectate.SpectateNext
	
	workspace.CurrentCamera.CameraType = Enum.CameraType.Scriptable
	workspace.CurrentCamera.CameraSubject = workspace.Rig.Humanoid
	
	local spectators = {}
	
	for _, plr in ipairs(PS:GetPlayers()) do
		if plr.Team == teams.players then
			table.insert(spectators, plr)
			print(plr)
		end
		
		if #spectators == 1 then
			table.insert(spectators, workspace.Rig)
		end
	end
	
	local currentIndex = 0
	
	leftArrow.MouseButton1Click:Connect(function()
		currentIndex = currentIndex + 1
		if currentIndex > #spectators then
			currentIndex = 1
		end

		if spectators[currentIndex] then
			workspace.CurrentCamera.CameraSubject = spectators[currentIndex].Character:FindFirstChild("Humanoid")
		end
	end)
	
	rightArrow.MouseButton1Click:Connect(function()
		currentIndex = currentIndex + 1
		if currentIndex > #spectators then
			currentIndex = 1
		end

		if spectators[currentIndex] then
			workspace.CurrentCamera.CameraSubject = spectators[currentIndex].Character:FindFirstChild("Humanoid")
		end
	end)
end

function rounds:CheckTeams()
	local players = PS:GetPlayers()
	
	for _, plr in ipairs(players) do
		if plr.Team == TS.players then
			table.insert(playersAlive, plr)
		end
		
		for _, plr in pairs(playersAlive) do
			while task.wait(1) do
				print(plr)
			end
		end
		
		plr.Character.Humanoid.Died:Connect(function()
			table.remove(playersAlive, plr)
		end)
	end
end

function rounds:TeamChange(plr : Player)
	print(plr.Name)
	plr.Team = teams.spectators
	spectateGui(plr)
end

PS.PlayerAdded:Connect(function(plr)
	plr.CharacterAdded:Connect(function(char)
		char.Humanoid.Died:Connect(function()
			print(char)
			rounds:TeamChange(plr)
			rounds:CheckTeams()
		end)
	end)
end)

return rounds

no worries! the camera updates properly once you comment out (or delete) the line:
workspace.CurrentCamera.CameraType = Enum.CameraType.Scriptable
if your goal is custom camera control and you want it to be set to Scriptable, then you’ll need to manually update the camera’s CFrame value.

i’d also like to point out that, presuming you’re calling the module from the client, the player’s change of teams won’t be shown on server and thus won’t replicate to other players. changing a player’s team is something that needs to be done on the server for everyone to see it, so i’d recommend using a remote for that.

It is called on the server, but I’ll try that!

This code needs to be called on the client. The server cannot dectect GUI button clicks nor can it change the camera subject of clients

Ok, ill change the code to be client-sided

Still doesn’t work, it just resests the camera back to the player

How many players are you testing with?

Change that to

leftArrow.Activated

Last, is this a LocalScript?

Its a modulescript called by a local script

Also, slightly unrelated, since I started this script, this error has appeared:


Honestly, I think it is just studio, but whatever

Do you know the exact issue, like if its a problem with just the camera or the index isnt working or your button clicks aren’t being detected?

I think the issue is with the index or camera

I have some tests so you know exactly what the problem is, making it much easier to solve.

To determine if it is the camera or the index you can use print statments on the index and see if it goes 1,2,3,4,5 and then when it runs out of players back to 1. If it does this then the index may be working. To know for sure print the player that matches the index Players[3]. If a player comes up then the index is fine.

For the camera see who it goes to.

workspace.CurrentCamera.CameraSubject = spectators[currentIndex].Character:FindFirstChild(“Humanoid”)

Here you can do

print("spectators[currentIndex]")

If it does nil then something is wrong with the table.

You can also print the table spectators and show me what it looks like.

Nvm I fixed it, but my new system resets the camera back to the character