Instance not a valid member of player but WaitForChild not working

I’m getting this error when I run my experience.

Stats is not a valid member of Player “Players.Player2” - Server - ServerScript:113

Here is where I declare the stats for the player (server script).

game:GetService("Players").PlayerAdded:Connect(function(player)
	local statsFolder = Instance.new("Folder")
	statsFolder.Parent = player
	statsFolder.Name = "Stats"

	local strength = Instance.new("IntValue")
	strength.Parent = statsFolder
	strength.Value = 10
	strength.Name = "Strength"

	local agility = Instance.new("IntValue")
	agility.Parent = statsFolder
	agility.Value = 10
	agility.Name = "Agility"

	local defense = Instance.new("IntValue")
	defense.Parent = statsFolder
	defense.Value = 10
	defense.Name = "Defense"

	local speed = Instance.new("IntValue")
	speed.Parent = statsFolder
	speed.Value = 10
	speed.Name = "Speed"

	local hp = Instance.new("IntValue")
	hp.Parent = statsFolder
	hp.Value = 10
	hp.Name = "HP"

	local mana = Instance.new("IntValue")
	mana.Parent = statsFolder
	mana.Value = 10
	mana.Name = "Mana"

	local level = Instance.new("IntValue")
	level.Parent = statsFolder
	level.Value = 1
	level.Name = "Level"

	local xp = Instance.new("IntValue")
	xp.Parent = statsFolder
	xp.Value = 0
	xp.Name = "XP"

	local gold = Instance.new("IntValue")
	gold.Parent = statsFolder
	gold.Value = 0
	gold.Name = "Gold"

	local gems = Instance.new("IntValue")
	gems.Parent = statsFolder
	gems.Value = 0
	gems.Name = "Gems"

	local weapon = Instance.new("IntValue")
	weapon.Parent = statsFolder
	weapon.Value = "sword"
	weapon.Name = "Weapon"
	
end)

A few lines later I define a function wherein I call upon the stats I have already created when the player joined:

local function turnHandler()
	repeat
		Players.PlayerAdded:Wait()
	until #Players:GetPlayers() == 2 -- CHANGE TO 2
	
	local player1 = Players:GetChildren()[1]
	local player2 = Players:GetChildren()[2]
	local attacker
	local turnActive = ReplicatedStorage:WaitForChild("Player1Turn")
	--initiative scoring
	local player1Init = player1.Stats.Speed.Value
	local player2Init = player2.Stats.Speed.Value -- line 113
	print(player1Init, player2Init)

At first I figured the stats folder just didn’t load in yet so I used WaitForChild like this:

--initiative scoring
	local player1Init = player1:WaitForChild("Stats").Speed.Value
	local player2Init = player2:WaitForChild("Stats").Speed.Value -- line 113

But after doing this and running the game the players would no longer spawn in at all, but they did previously. No errors, but the players would fail to spawn into the workspace at all. I’m not sure what to do here, as I have no idea why WaitForChild isn’t working and I don’t know why I’m receiving the original error in the first place. It also seems odd that only line 113 is throwing and error and not 112, despite them basically being the same thing.

Try to name the folder to “Stats” before parenting it to the player

The code will halt after error occurred, that’s why there is only 1 error

I did this and the error still shows.

First thing’s first:
Parenting stuff before all of its properties are defined is bad practice, and it’s not that difficult to adapt to doing it “properly” (I could go into the details but that’s a different topic.)

Now, before I can fix your code, where are you calling “turnHandler”?

I assume it’s just called in the global scope and not under anything else. If I’m wrong please clarify, but if so, you will indeed need to wait for the stats folder since it’ll start executing immediately when the 2nd player joins. So use WaitForChild.

To add on to my first point: If we fix your code and do it properly here,

game:GetService("Players").PlayerAdded:Connect(function(player)
	local statsFolder = Instance.new("Folder")
	statsFolder.Name = "Stats"

	local strength = Instance.new("IntValue")
	strength.Value = 10
	strength.Name = "Strength"

	local agility = Instance.new("IntValue")
	agility.Value = 10
	agility.Name = "Agility"

	local defense = Instance.new("IntValue")
	defense.Value = 10
	defense.Name = "Defense"

	local speed = Instance.new("IntValue")
	speed.Value = 10
	speed.Name = "Speed"

	local hp = Instance.new("IntValue")
	hp.Value = 10
	hp.Name = "HP"

	local mana = Instance.new("IntValue")
	mana.Value = 10
	mana.Name = "Mana"

	local level = Instance.new("IntValue")
	level.Value = 1
	level.Name = "Level"

	local xp = Instance.new("IntValue")
	xp.Value = 0
	xp.Name = "XP"

	local gold = Instance.new("IntValue")
	gold.Value = 0
	gold.Name = "Gold"

	local gems = Instance.new("IntValue")
	gems.Value = 0
	gems.Name = "Gems"

	local weapon = Instance.new("IntValue")
	weapon.Value = "sword"
	weapon.Name = "Weapon"

  strength.Parent = statsFolder
  agility.Parent = statsFolder
  defense.Parent = statsFolder
  speed.Parent = statsFolder
  hp.Parent = statsFolder
  mana.Parent = statsFolder
  level.Parent = statsFolder
  xp.Parent = statsFolder
  gold.Parent = statsFolder
  gems.Parent = statsFolder
  weapon.Parent = statsFolder

  statsFolder.Parent = player
end)

We now ensure that each stat value exists when the stats folder is parented.
If you parent it beforehand, it would require an extra WaitForChild for the Speed value.
This is a good example of why we should only parent things after its properties and children (and their properties, etc…) exist/are set.

1 Like

image
Uh, is this the issue?

No, that’s dedicated support for adding leaderstat values. It’s a good thought, but he’s trying to define a folder that strictly holds data values that would clutter the leaderboard and are rather for instantiating (objectifying) the data values for later use.

Good idea/suggestion though.

1 Like

Thank you for this tip, I had no idea this was bad practice. I have rewritten some stuff and realized my problem is that the player1 and player2 variables are nil, because I assigned their values inside a local scope and am trying to use the variables outside of that scope, but they’re just nil because I haven’t assigned a value outside of a local scope.

This is the first part of the turnHandler() function:

local function turnHandler()
	player1 = nil
	player2 = nil
	repeat
		task.wait()
		print("Waiting")
	until #Players:GetChildren() == 2
	for i, player in ipairs(Players:GetChildren()) do
		if player.Stats.PlayerNumber == 1 then
			player1 = player
			print("Player 1: ", player1)
		elseif player.Stats.PlayerNumber == 2 then
			player2 = player
			print("Player 2: ", player2)
		else
			print("ERROR")
		end
	end
	
	--local player1 = Players:GetChildren()[1]
	--local player2 = Players:GetChildren()[2]
	local attacker
	local turnActive = ReplicatedStorage:WaitForChild("Player1Turn")
	--initiative scoring
	print("Player 1: ",player1) -- returns nil because of scope
	local player1Init = player1:WaitForChild("Stats"):WaitForChild("Speed").Value
	local player2Init = player2:WaitForChild("Stats"):WaitForChild("Speed").Value

How can I update those player1 and player2 variables for outside access? Or is there an easier way for me to do this?

one option is to return player1 and player2 at the end of the function or when the function completes i.e.

local function turnHandler()
 local player1 = nil
 local player2 = nil

 return player1, player2
end

player1,player2 = turnHandler()

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