Attempt to index nil with 'Character'

So, here I am with the spectate script. I’m quite confused on why the error shows up but for some reason this line of code gives me an error:

camera.CameraSubject = player.Character.Humanoid

If your interested in seeing the whole function:

previous.MouseButton1Click:Connect(function()
	local players = {}
	gameModule.PlayersAlive(players)
	for i, player in pairs (players) do
		print(player)
		wait()
	end
	local max = #players
	num = num - 1
	if num < 1 then
		num = max
	end
	local player = players[num]
	camera.CameraSubject = player.Character.Humanoid
	status.Text = player.Name
end)

The error:

I tried looking for any other situations related to mine but none fitted my topic. Help would be very appreciated.

1 Like

So basically what the error is telling you is that the variable “player” is not equal to anything

1 Like

Yes, so how would I be able to get the humanoid from a table of players.

Okay so instead of storing the players names in the table i would suggest storing their UserId so you can simply do

local plr = game:GetService("Players"):GetPlayerByUserId(PLAYER_ID_HERE)  

then you can use plr.Character

Pretty sure player is nil for him

Yes, indeed. But my script works like this:

I get the players, teleport them into the game and use the spectate to only spectate players in a round.

ummm, not really the issue tho. You see the module function is the one getting the players there is no need to do that again.

function moduleFunction.PlayersAlive(playersInSpectate)
	for i, player in pairs (playersInRound) do
		table.insert(playersInSpectate, player)
		print(player)
		wait()
	end
end

Yeah, only just noticed what you were trying to do. Is the player still returning nil or is it only the character? If it’s only the character then you need to search the players for the player name in the table.

Try doing what i suggested, instead of storing Players try to store userIds and just use :GetPlayerByUserId()

image

If I were to do that I would have to redo the whole script:

module:

local moduleFunction = {}
local playersInRound = {}
local connections = {}

local playerInfo = { --//Example Of What your storing in Table
	AFK = false; --// If they will be counted in match start
	InRound = false --// Any other stats you want
}

function moduleFunction.ReturnPlayersInfo()
	return playerInfo
end
---------------------------------------------------------------------------------------------------------------------------
-- // Game Functions \\ --
---------------------------------------------------------------------------------------------------------------------------
function moduleFunction.AddValue()
	local Players = game:GetService("Players")
	Players.PlayerAdded:Connect(function(player)

		local isPlaying  = Instance.new("BoolValue")
		isPlaying.Name = "IsPlaying" 
		isPlaying.Parent = player 

	end)
end

function moduleFunction.Countdown(numS, numE, change, parent, text)
	for i = numS, numE, change do
		parent.Value = text..i
		wait(1)
	end
end

function moduleFunction.AddPlayer(player)
	if player:IsA("Player") then
		if playerInfo.AFK == false then
			playerInfo.InRound = true
			print(player)
			table.insert(playersInRound, player) -- add all players to table
			connections[player.Name] = player.Character.Humanoid.Died:Connect(function()
				table.remove(playersInRound, table.find(playersInRound, player))
			end)
		elseif playerInfo.AFK == true then
			warn("Player is afk. Was not added to the list")
			playerInfo.InRound = false
		end	
	end
end

function moduleFunction.PlayerLeft()
	connections["Removing"] = game.Players.PlayerRemoving:Connect(function(player) -- remove player from list if they leave
		local playerLeft = table.find(playersInRound, player)
		if playerLeft then
			table.remove(playersInRound, playerLeft)
			playerInfo.InRound = false
		end
	end)
end

function moduleFunction.TileDissaper(parent)
	for _,Part in ipairs(parent:GetChildren()) do
		if Part:IsA("Part") then
			Part.OnTouchedTile.Touched:Connect(function(hit)
				if hit.Parent and hit.Parent:FindFirstChild("Humanoid") then
					if Part.Transparency == 0 then
						for i = 0, 1, 0.0625 do
							Part.Transparency = i
							wait()
						end
						Part:Destroy()
					end
				end
			end)
		end
	end
end

--[[function moduleFunction.PlayersAlive(playersInSpectate)
	for i, player in pairs (playersInRound) do
		table.insert(playersInSpectate, player)
		print(player)
		wait()
	end
end --]]


function moduleFunction.CheckWinner(parent)
	if #playersInRound > 1 then
		while #playersInRound >= 2 do
			parent.Value = "Game in progress"
			wait()
			if #playersInRound == 1 then
				local player = playersInRound[1]
				print("The Winner is: " .. player.Name)
				parent.Value = player.Name .. " has won this round!"
				wait(5)
			elseif #playersInRound == 0 then
				print("There was not a single winner.")
				parent.Value = "No one won this round"
				wait(5)
			end
		end
	end
end

function moduleFunction.RemovePlayer()
	-- Kill the players
	for _, connection in pairs(connections) do -- disconnect connections to prevent memory leaks
		connection:Disconnect()
		wait()
	end

	for _, player in pairs(playersInRound)do
		player:LoadCharacter()
		wait()
	end	
	
	playerInfo.InRound = false
	playersInRound = {}
end 

return moduleFunction

I think the Module script isnt returning anything, so if youre trying to get a table of players from the Module, your script is not scripted correctly to accept a value

local PlayerTable = gameModule.PlayersAlive(players)

It is I just pasted the wrong one lol.

local moduleFunction = {}
local playersInRound = {}
local connections = {}

local playerInfo = { --//Example Of What your storing in Table
	AFK = false; --// If they will be counted in match start
	InRound = false --// Any other stats you want
}

function moduleFunction.ReturnPlayersInfo()
	return playerInfo
end
---------------------------------------------------------------------------------------------------------------------------
-- // Game Functions \\ --
---------------------------------------------------------------------------------------------------------------------------
function moduleFunction.AddValue()
	local Players = game:GetService("Players")
	Players.PlayerAdded:Connect(function(player)

		local isPlaying  = Instance.new("BoolValue")
		isPlaying.Name = "IsPlaying" 
		isPlaying.Parent = player 

	end)
end

function moduleFunction.Countdown(numS, numE, change, parent, text)
	for i = numS, numE, change do
		parent.Value = text..i
		wait(1)
	end
end

function moduleFunction.AddPlayer(player)
	if player:IsA("Player") then
		if playerInfo.AFK == false then
			playerInfo.InRound = true
			print(player)
			table.insert(playersInRound, player) -- add all players to table
			connections[player.Name] = player.Character.Humanoid.Died:Connect(function()
				table.remove(playersInRound, table.find(playersInRound, player))
			end)
		elseif playerInfo.AFK == true then
			warn("Player is afk. Was not added to the list")
			playerInfo.InRound = false
		end	
	end
end

function moduleFunction.PlayerLeft()
	connections["Removing"] = game.Players.PlayerRemoving:Connect(function(player) -- remove player from list if they leave
		local playerLeft = table.find(playersInRound, player)
		if playerLeft then
			table.remove(playersInRound, playerLeft)
			playerInfo.InRound = false
		end
	end)
end

function moduleFunction.TileDissaper(parent)
	for _,Part in ipairs(parent:GetChildren()) do
		if Part:IsA("Part") then
			Part.OnTouchedTile.Touched:Connect(function(hit)
				if hit.Parent and hit.Parent:FindFirstChild("Humanoid") then
					if Part.Transparency == 0 then
						for i = 0, 1, 0.0625 do
							Part.Transparency = i
							wait()
						end
						Part:Destroy()
					end
				end
			end)
		end
	end
end

function moduleFunction.PlayersAlive()
	return playersInRound
end

function moduleFunction.CheckWinner(parent)
	if #playersInRound > 1 then
		while #playersInRound >= 2 do
			parent.Value = "Game in progress"
			wait()
			if #playersInRound == 1 then
				local player = playersInRound[1]
				print("The Winner is: " .. player.Name)
				parent.Value = player.Name .. " has won this round!"
				wait(5)
			elseif #playersInRound == 0 then
				print("There was not a single winner.")
				parent.Value = "No one won this round"
				wait(5)
			end
		end
	end
end

function moduleFunction.RemovePlayer()
	-- Kill the players
	for _, connection in pairs(connections) do -- disconnect connections to prevent memory leaks
		connection:Disconnect()
		wait()
	end

	for _, player in pairs(playersInRound)do
		player:LoadCharacter()
		wait()
	end	
	
	playerInfo.InRound = false
	playersInRound = {}
end 

return moduleFunction

And I may have gave the old mouseclick function too.

Here it is

previous.MouseButton1Click:Connect(function()
	local players = gameModule.PlayersAlive()
	local max = #players
	num = num - 1
	if num < 1 then
		num = max
	end
	local player = players[num]
	local playerLocation = game.Players:FindFirstChild(player)
	camera.CameraSubject = playerLocation.Character.Humanoid
	status.Text = player.Name
end)

Sorry for the confusion! These are the 2 you should be looking at right here.

MouseButton1Click should still work

Same Error as before:

image

local playerLocation = game.Players:FindFirstChild(player)
previous.MouseButton1Click:Connect(function()
    local players = gameModule.PlayersAlive()
    local max = #players
    num = num - 1
    if num < 1 then
        num = max
    end
    if num > 0 then
        local player = players[num]
        local playerLocation = game.Players:FindFirstChild(player.Name)
        if playerLocation then
            camera.CameraSubject = playerLocation.Character.Humanoid
            status.Text = player.Name
        end
    end
end)

Doesn’t seem to work at all when I test it out with 2 players
Would you like to see the whole spectate script?

local debounce = false
local toggle = script.Parent.Parent.Buttons.SpectateButton.ImageButtonRoundify12px
local frame = script.Parent
local otherFrame = script.Parent.Parent.InventoryFrame
local otherFrame2 = script.Parent.Parent.SettingsFrame
local previous = frame.PrevButton.Button
local next = frame.NextButton.Button
local status = frame.RoundifyImage12px.Status
local camera = game.Workspace.CurrentCamera
local num = 1
local gameModule = require(game.ReplicatedStorage.GameModule)



status.Text = game.Players.LocalPlayer.Name

toggle.MouseButton1Click:connect(function() 
	-- local players = {}
	-- gameModule.PlayersAlive(players)
	-- if #players < 1 then return end
	otherFrame.Visible = false
	otherFrame.Position = UDim2.new(0.499, 0, 0.369, 0)
	otherFrame2.Visible = false
	otherFrame2.Position = UDim2.new(0.499, 0, 0.369, 0)
	if frame.Visible == false then
		debounce = true
		frame.Visible = true
		frame:TweenPosition(UDim2.new(0.218, 0, 0.646, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 0.0625, true)
		debounce = false
	elseif frame.Visible == true then
		debounce = true
		frame.Visible = false
		frame.Position = UDim2.new(0.218, 0, 0.716, 0)
		debounce = false
	end	
end)

previous.MouseButton1Click:Connect(function()
	local players = gameModule.PlayersAlive()
	local max = #players
	num = num - 1
	if num < 1 then
		num = max
	end
	if num > 0 then
		local player = players[num]
		local playerLocation = game.Players:FindFirstChild(player.Name)
		if playerLocation then
			camera.CameraSubject = playerLocation.Character.Humanoid
			status.Text = player.Name
		end
	end
end)

next.MouseButton1Click:Connect(function()
	local players = gameModule.PlayersAlive()
	local max = #players
	num = num + 1
	if num > max then
		num = 1
	end
	if num > 0 then
		local player = players[num]
		local playerLocation = game.Players:FindFirstChild(player.Name)
		if playerLocation then
			camera.CameraSubject = playerLocation.Character.Humanoid
			status.Text = player.Name
		end
	end
end)

frame.Changed:Connect(function()
	if not frame.Visible then
		camera.CameraSubject = game.Players.LocalPlayer.Character.Humanoid
		status.Text = game.Players.LocalPlayer.Name
	end
end)

Try debugging your script using prints to see where exactly the issue occurs.

I debugged it and I think it lies with code if num > 0 then

previous.MouseButton1Click:Connect(function()
	local players = gameModule.PlayersAlive()
	print("clicked")
	local max = #players
	num = num - 1
	if num < 1 then
		num = max
	end
	if num > 0 then
		print("num is greater than 0")
		local player = players[num]
		local playerLocation = game.Players:FindFirstChild(player.Name)
		if playerLocation then
			print("player location")
			camera.CameraSubject = playerLocation.Character.Humanoid
			status.Text = player.Name
		end
	end
end)