ReplicatedStorage.CoinHandler:21: attempt to index nil with 'FindFirstChild'

local coins = {}

local Debris = game:GetService("Debris")

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

local Tokens = workspace:FindFirstChild("Tokens")
local CoinFolder = ServerStorage:FindFirstChild("Coins")

local LS = nil

coins.CoinTaken = function(player, CoinType, TheCoin, state)
	
	if not state then
		state = true
		
		local Amount = 0
	
		local PlayerToFind = Players:GetPlayerFromCharacter(player.Parent)
		LS = PlayerToFind:FindFirstChild("leaderstats")
		
		LS.Tokens.Value += TheCoin.Amount.Value
		Amount = TheCoin.Timer.Value
	
		local PreviousPos = TheCoin.Position
		TheCoin:Destroy()

		-- WAIT 5 seconds to spawn that coin again
		task.delay(Amount, function()
			coins.New(PreviousPos, CoinType)
			state = true
		end)
	end
end

coins.New = function(position, Type)
	local desiredCoin = CoinFolder:FindFirstChild(Type)
	local NewCoin = desiredCoin:Clone()

	NewCoin.Parent = Tokens
	NewCoin.Position = position

	NewCoin.Touched:Connect(function(player)
		coins.CoinTaken(player, Type, NewCoin, false)
	end)
end

return coins

I’m unsure why it keeps on giving me this error whenever I attempt to use FindFirstChild.

I’ve pretty much tried a variety of methods but it just can’t get leaderstats. Which is odd since it does exist.

add

if not PlayerToFind then return end

after

Ah yes! Thank you for helping! I just forgot about those type of lines that can solve those problems.

1 Like

This is a modulescript, right? I’d recommend you write your functions like this instead:

function coins.CoinTaken(player, CoinType, TheCoin, state)
    ... -- code
end)

function coins.New(position, Type)
    ...
end)

If you want to use OOP this is crucial. This allows you to edit specific objects without passing them in. Example of an OOP implementation of this

local Coin = {}
Coin.__index = Coin

function Coin.new(position: Vector3, type: string) -- This just states that the variables will have these types
	local self = setmetatable({}, Coin)

	self.Model = CoinFolder:FindFirstChild(type):Clone()
	self.Type = type
	self.State = true -- What is this used for?
	self.Model.Touched:Once(function(player: BasePart)
		self:CoinTaken(player, false)
	end)

	return self
end

function Coin:CoinTaken(player: BasePart)
	if not self.State then
		self.State = true

		... -- Do whatever you want to do when it is touched
	end
end
1 Like

Ah I see. This helps a lot and I was confused with them at first.

Addition to @msix29’s solution. You dont need to certainly put the if statement there, because you would need to have

if not LS then return end

As well, because if the player did not receive a leaderstats folder, then it will break once again. So if you want to combine the code:

local PlayerToFind = Players:GetPlayerFromCharacter(player.Parent)
if not PlayerToFind then return end

LS = PlayerToFind:FindFirstChild("leaderstats")
if not LS then return end

Then you can do the following:

local PlayerToFind = Players:GetPlayerFromCharacter(player.Parent)
LS = PlayerToFind and PlayerToFind:FindFirstChild("leaderstats")
if not LS then return end

It is an if statement basically inside the variable.

2 Likes

I sort of get it now! Thanks! It’s pretty hard to remember all the ways that you can prevent errors!

1 Like

Quick explanation for the following part,

What it says there is basically the same as:

if PlayerToFind then
   LS = PlayerToFind:FindFirstChild("leaderstats")
else 
   LS = PlayerToFind -- PlayerToFind is nil in this case so it would actually be
   LS = nil
end
1 Like

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