Attempt to index nil with FindFirstChild error

Hi! I’ve been working on a game and just scripted a voting system, but I have a strange error.

When the 2 players duel for the first time, everything works. When they go a second time, it breaks. I don’t know why and some simple debugging has told me that the reset() function has nothing to do with it. (I thought this because it’s (as far as I know) the only function that is called in between duels).

The error is on this line:

gameTP = game.Workspace.Maps:FindFirstChild(chosenMap..numberEntrance):FindFirstChild("GameTP")
The whole part of the script that's erroring
local function votingTimerFunc(player1, player2)
	repeat
		task.wait(1)
		votingTime -= 1
		votingTimerUpdateEvent:FireClient(player1, votingTime)
		votingTimerUpdateEvent:FireClient(player2, votingTime)
	until votingTime == 0
	votingTime = votingTimeMax
	
	local currentWinner = nil
	local currentMostCount = 0
	
	for name, count in pairs(votes) do
		if (count >= currentMostCount) then
			currentMostCount = count
			currentWinner = name
		end
	end
	
	chosenMap = currentWinner
	print(chosenMap..numberEntrance)
	gameTP = game.Workspace.Maps:FindFirstChild(chosenMap..numberEntrance):FindFirstChild("GameTP")
	endPart = game.Workspace.Maps:FindFirstChild(chosenMap..numberEntrance):FindFirstChild("EndPart")
	
	endVotingEvent:FireClient(player1)
	endVotingEvent:FireClient(player2)
	
	start(player1, player2)
end
The entire script (please ignore my messy code, I am by no means experienced in scripting
local players = game:GetService("Players")
local replicated = game:GetService("ReplicatedStorage")
local ts = game:GetService("TweenService")

local enterEvent = replicated:WaitForChild("PlayerEntered")
local exitEvent = replicated:WaitForChild("PlayerExit")

local winEvent = replicated:WaitForChild("WinLoseEvents"):WaitForChild("WinEvent")
local loseEvent = replicated:WaitForChild("WinLoseEvents"):WaitForChild("LoseEvent")

local DisableControlsEvent = replicated:WaitForChild("PlayerControlsEvents"):WaitForChild("DisableControls")
local EnableControlsEvent = replicated:WaitForChild("PlayerControlsEvents"):WaitForChild("EnableControls")

local StartCountdownEvent = replicated:WaitForChild("StartCountdown")
local UpdateCountdownEvent = replicated:WaitForChild("UpdateCountdown")
local EndCountdownEvent = replicated:WaitForChild("EndCountdown")

local votedEvent = replicated:WaitForChild("VotingEvents"):WaitForChild("PlayerVoted")
local startVotingEvent = replicated:WaitForChild("VotingEvents"):WaitForChild("StartVoting")
local endVotingEvent = replicated:WaitForChild("VotingEvents"):WaitForChild("EndVoting")
local votingTimerUpdateEvent = replicated:WaitForChild("VotingEvents"):WaitForChild("VotingTimerUpdate")

local numberEntrance = script.Parent.Number.Value

local pad1 = script.Parent.Pad1
local pad2 = script.Parent.Pad2

local pad1Frame = script.Parent.UIPart.SurfaceGui.Frame.Pad1Frame
local pad2Frame = script.Parent.UIPart.SurfaceGui.Frame.Pad2Frame

local pad1Icon = pad1Frame.ImageLabel
local pad2Icon = pad2Frame.ImageLabel

local pad1PlayerDisplay = pad1Frame.PlayerDisplay
local pad2PlayerDisplay = pad2Frame.PlayerDisplay

local pad1PlayerName = pad1Frame.PlayerName
local pad2PlayerName = pad2Frame.PlayerName

local pad1PlayerAmount = pad1Frame.PlayerAmount
local pad2PlayerAmount = pad2Frame.PlayerAmount

local campart = script.Parent.CamPos

local tpPart = script.Parent.TPPart

local gameTP = nil
local endPart = nil

local pad1Player = nil
local pad2Player = nil

local ongoing = false

local chosenMap = nil

local votingTimeMax = 10
local votingTime = votingTimeMax

local votes = {
	["Construction"] = 0,
	["Temple"] = 0,
	["MagicalForest"] = 0
}

local player1Vote = nil
local player2Vote = nil

pad1.Material = Enum.Material.SmoothPlastic
pad2.Material = Enum.Material.SmoothPlastic

pad1PlayerAmount.Text = "0/1"
pad2PlayerAmount.Text = "0/1"

pad1PlayerDisplay.Text = ""
pad2PlayerDisplay.Text = ""

pad1PlayerName.Text = ""
pad2PlayerName.Text = ""

local maxCountdown = 5
local countdownval = maxCountdown

local defaultIcon = "rbxassetid://0"
pad1Icon.Image = defaultIcon
pad2Icon.Image = defaultIcon

local function countdown(player1, player2)
	print("Countdown Started")
	
	StartCountdownEvent:FireClient(player1)
	StartCountdownEvent:FireClient(player2)
	
	repeat
		UpdateCountdownEvent:FireClient(player1, countdownval)
		UpdateCountdownEvent:FireClient(player2, countdownval)
		
		task.wait(1)
		
		countdownval -= 1
	until countdownval == 1
	countdownval = maxCountdown
	
	UpdateCountdownEvent:FireClient(player1, 1)
	UpdateCountdownEvent:FireClient(player2, 1)
	
	EndCountdownEvent:FireClient(player1)
	EndCountdownEvent:FireClient(player2)
	
	task.wait(1)
	
	EnableControlsEvent:FireClient(player1)
	EnableControlsEvent:FireClient(player2)
end

local function reset(pad)
	chosenMap = nil
	votingTime = votingTimeMax
	countdownval = maxCountdown
	gameTP = nil
	endPart = nil
	ongoing = false

	votes.Construction = 0
	votes.Temple = 0
	votes.MagicalForest = 0

	if pad == pad1 then

		if game.Players:FindFirstChild(tostring(pad1Player)) then
			pad1Player.Character:WaitForChild("HumanoidRootPart").CFrame = tpPart.CFrame
			exitEvent:FireClient(pad1Player)
		end

		pad1Player = nil

		pad1PlayerAmount.Text = "0/1"
		pad1PlayerDisplay.Text = ""
		pad1PlayerName.Text = ""
		pad1Icon.Image = defaultIcon
		pad1.Material = Enum.Material.SmoothPlastic
		pad1.BrickColor = BrickColor.new("Dark stone grey")
	elseif pad == pad2 then

		if game.Players:FindFirstChild(tostring(pad2Player)) then
			pad2Player.Character:WaitForChild("HumanoidRootPart").CFrame = tpPart.CFrame
			exitEvent:FireClient(pad2Player)
		end

		pad2Player = nil

		pad2PlayerAmount.Text = "0/1"
		pad2PlayerDisplay.Text = ""
		pad2PlayerName.Text = ""
		pad2Icon.Image = defaultIcon
		pad2.Material = Enum.Material.SmoothPlastic
		pad2.BrickColor = BrickColor.new("Dark stone grey")
	end
end

local function start(player1, player2)

	ongoing = true

	exitEvent:FireClient(player1)
	exitEvent:FireClient(player2)

	DisableControlsEvent:FireClient(player1)
	DisableControlsEvent:FireClient(player2)

	player1.Character:WaitForChild("HumanoidRootPart").CFrame = gameTP.CFrame
	player2.Character:WaitForChild("HumanoidRootPart").CFrame = gameTP.CFrame
	
	if endPart then
		endPart.Touched:Connect(function(hit)
			local char = hit.Parent

			if char:FindFirstChild("Humanoid") and ongoing then
				ongoing = false

				local player = players:GetPlayerFromCharacter(char)

				if player == pad1Player then
					winEvent:FireClient(pad1Player)
					loseEvent:FireClient(pad2Player)
				elseif player == pad2Player then
					winEvent:FireClient(pad2Player)
					loseEvent:FireClient(pad1Player)
				end

				reset(pad1)
				reset(pad2)
			end
		end)
	end

	countdown(player1, player2)
end

local function votingTimerFunc(player1, player2)
	repeat
		task.wait(1)
		votingTime -= 1
		votingTimerUpdateEvent:FireClient(player1, votingTime)
		votingTimerUpdateEvent:FireClient(player2, votingTime)
	until votingTime == 0
	votingTime = votingTimeMax
	
	local currentWinner = nil
	local currentMostCount = 0
	
	for name, count in pairs(votes) do
		if (count >= currentMostCount) then
			currentMostCount = count
			currentWinner = name
		end
	end
	
	chosenMap = currentWinner
	print(chosenMap..numberEntrance)
	gameTP = game.Workspace.Maps:FindFirstChild(chosenMap..numberEntrance):FindFirstChild("GameTP")
	endPart = game.Workspace.Maps:FindFirstChild(chosenMap..numberEntrance):FindFirstChild("EndPart")
	
	endVotingEvent:FireClient(player1)
	endVotingEvent:FireClient(player2)
	
	start(player1, player2)
end

local function startVoting(player1, player2)
	startVotingEvent:FireClient(player1)
	startVotingEvent:FireClient(player2)
	
	votingTimerFunc(player1, player2)
end

votedEvent.OnServerEvent:Connect(function(votingPlayer, map)
	if pad1Player and pad2Player then
		if votingPlayer == pad1Player then
			if player1Vote == "Construction" then
				votes.Construction -= 1
				if map == "Construction" then
					votes.Construction += 1
					player1Vote = map
				elseif map == "Temple" then
					votes.Temple += 1
					player1Vote = map
				elseif map == "MagicalForest" then
					votes.MagicalForest += 1
					player1Vote = map
				end
			elseif player1Vote == "Temple" then
				votes.Temple -= 1
				if map == "Construction" then
					votes.Construction += 1
					player1Vote = map
				elseif map == "Temple" then
					votes.Temple += 1
					player1Vote = map
				elseif map == "MagicalForest" then
					votes.MagicalForest += 1
					player1Vote = map
				end
			elseif player1Vote == "MagicalForest" then
				votes.MagicalForest -= 1
				if map == "Construction" then
					votes.Construction += 1
					player1Vote = map
				elseif map == "Temple" then
					votes.Temple += 1
					player1Vote = map
				elseif map == "MagicalForest" then
					votes.MagicalForest += 1
					player1Vote = map
				end
			elseif player1Vote == nil then
				if map == "Construction" then
					votes.Construction += 1
					player1Vote = map
				elseif map == "Temple" then
					votes.Temple += 1
					player1Vote = map
				elseif map == "MagicalForest" then
					votes.MagicalForest += 1
					player1Vote = map
				end
			end
			votedEvent:FireAllClients(player1Vote, pad1Player, pad2Player)
		end
		if votingPlayer == pad2Player then
			if player2Vote == "Construction" then
				votes.Construction -= 1
				if map == "Construction" then
					votes.Construction += 1
					player2Vote = map
				elseif map == "Temple" then
					votes.Temple += 1
					player2Vote = map
				elseif map == "MagicalForest" then
					votes.MagicalForest += 1
					player2Vote = map
				end
			elseif player2Vote == "Temple" then
				votes.Temple -= 1
				if map == "Construction" then
					votes.Construction += 1
					player2Vote = map
				elseif map == "Temple" then
					votes.Temple += 1
					player2Vote = map
				elseif map == "MagicalForest" then
					votes.MagicalForest += 1
					player2Vote = map
				end
			elseif player2Vote == "MagicalForest" then
				votes.MagicalForest -= 1
				if map == "Construction" then
					votes.Construction += 1
					player2Vote = map
				elseif map == "Temple" then
					votes.Temple += 1
					player2Vote = map
				elseif map == "MagicalForest" then
					votes.MagicalForest += 1
					player2Vote = map
				end
			elseif player2Vote == nil then
				if map == "Construction" then
					votes.Construction += 1
					player2Vote = map
				elseif map == "Temple" then
					votes.Temple += 1
					player2Vote = map
				elseif map == "MagicalForest" then
					votes.MagicalForest += 1
					player2Vote = map
				end
			end
			votedEvent:FireAllClients(player2Vote, pad2Player, pad1Player)
		end
	end
end)

players.PlayerRemoving:Connect(function(leavingPlayer)
	if leavingPlayer == pad1Player or leavingPlayer == pad2Player then
		if ongoing then
			ongoing = false
			reset(pad1)
			reset(pad2)
		else
			if leavingPlayer == pad1Player then
				reset(pad1)
			elseif leavingPlayer == pad2Player then
				reset(pad2)
			end
		end
	end
end)

exitEvent.OnServerEvent:Connect(function(player)
	if player == pad1Player then
		reset(pad1)
	elseif player == pad2Player then
		reset(pad2)
	end
end)

local function pad1Touch(hit)
	local char = hit.Parent
	if pad1Player == nil then
		if char:FindFirstChild("HumanoidRootPart") then
			pad1Player = players:GetPlayerFromCharacter(char)

			enterEvent:FireClient(pad1Player, campart)
			
			pad1.BrickColor = BrickColor.new("New Yeller")
			pad1.Material = Enum.Material.Neon

			pad1PlayerAmount.Text = "1/1"
			pad1PlayerDisplay.Text = pad1Player.DisplayName
			pad1PlayerName.Text = "@"..pad1Player.Name
			pad1Icon.Image = players:GetUserThumbnailAsync(pad1Player.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size420x420)
			
			if pad1Player and pad2Player then
				startVoting(pad1Player, pad2Player)
			end
		end
	end
end

local function pad2Touch(hit)
	local char = hit.Parent
	
	if pad2Player == nil then
		if char:FindFirstChild("HumanoidRootPart") then
			pad2Player = players:GetPlayerFromCharacter(char)

			enterEvent:FireClient(pad2Player, campart)
			
			pad2.BrickColor = BrickColor.new("New Yeller")
			pad2.Material = Enum.Material.Neon
			
			pad2PlayerAmount.Text = "1/1"
			pad2PlayerDisplay.Text = pad2Player.DisplayName
			pad2PlayerName.Text = "@"..pad2Player.Name
			pad2Icon.Image = players:GetUserThumbnailAsync(pad2Player.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size420x420)
			

			if pad1Player and pad2Player then
				startVoting(pad1Player, pad2Player)
			end
		end
	end
end

pad1.Touched:Connect(pad1Touch)
pad2.Touched:Connect(pad2Touch)
2 Likes

You have chained 2 FindFirstChilds together, so if the first one returns nil, then you are trying to call :FindFirstChild() on a nil value. FindFirstChild is used when you do not know if the child is actually present, so you should check to see if it actually exists, and if it does, then you can proceed to do things with it. Something like this should suffice:

local entrance = game.Workspace.Maps:FindFirstChild(chosenMap .. numberEntrance)
if entrance then
    local gameTP = entrance:FindFirstChild("GameTP")
    if gameTP then
        -- now you can do things with gameTP
    end
end

At the end of the day, however, the reason you are getting this error is because game.Workspace:FindFirstChild("chosenMap .. numberEntrance) returns nil, meaning the instance is not present. Maybe check explorer to make sure it exists (while testing the game and the script)

5 Likes

Okay. Is there any reason for it working the first time? (Also I just checked the explorer and the instance still exists)

Edit: I’m also still having the same issue

2 Likes

What does the error say in your console?

2 Likes

1 Like

Does the “ChosenMap” exist in the Maps folder after you got the voting results?

2 Likes

Yeah, it does. I just found out that there’s something wrong with the voting system as it chooses the wrong map.

1 Like

I just figured out the issue. My voting code was not resetting votes after rounds so I’m going to mark OptimisticSide’s suggestion as the solution because it was essentially correct. The thing that was being called didn’t exist.

1 Like

just so you know, this part of your code is heavily unoptimised, and can be easily redone in a fewer lines:

votedEvent.OnServerEvent:Connect(function(votingPlayer, map:string)
	if pad1Player and pad2Player then
		if votingPlayer == pad1Player then
			votes[map] += 1
			if player1Vote then
				votes[player1Vote] -= 1
			end
			player1Vote = map
			votedEvent:FireAllClients(player1Vote, pad1Player, pad2Player)
		elseif votingPlayer == pad2Player then
			votes[map] += 1
			if player2Vote then
				votes[player2Vote] -= 1
			end
			player2Vote = map
			votedEvent:FireAllClients(player2Vote, pad2Player, pad1Player)
		end
	end
end)
2 Likes

Thanks!! I knew that is was going to be an ABSOLUTE pain when it came to adding new maps but I didn’t know how to fix it.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.