Function keeps calling error

Hello devs, I have problem with script

function GetPlayer(ignore)
	local Players = game.Players:GetPlayers()
	local RandomPlayer = Players[math.random(1, #Players)]
	if RandomPlayer then
		if RandomPlayer.Name ~= ignore.Name then
			return RandomPlayer
		else
			return GetPlayer()
		end
	end
end

And it keeps showing

ServerScriptService.Main:27: attempt to index nil with 'Name'

This script is for random player choose and prevent from choosing one player ignore
Hope you can help me.

Probably because of this line since you aren’t returning a player back for the recursion

1 Like

Where do you define ignore when you call the function? The error is saying ignore is nil

It would be helpful if you provided the code where you call the function so we understand what data type is coming into the function. Since the issue is from trying to get a value inside of ignore that doesn’t exist.

function GetPlayer(ignore)
	local Players = game.Players:GetPlayers()
	local RandomPlayer = Players[math.random(1, #Players)]
	if RandomPlayer then
		if RandomPlayer.Name ~= ignore.Name then
			return RandomPlayer
		else
			return GetPlayer()
		end
	end
end

function DayNight()
	for _,player in pairs(game.Players:GetPlayers()) do
		if player:FindFirstChild("HasDied") then
			player.HasDied.Value = false
		end
	end
	workspace.DayMusic:Play()
	workspace.Day.Value = true
	wait(180)
	workspace.NightTime:Play()
	Night:Play()
	Night.Completed:Wait()
	workspace.Day.Value = false
	local Players = game.Players:GetPlayers()
	local RandomPlayer = Players[math.random(1, #Players)]
	local RandomHunter = GetPlayer(RandomPlayer)
	local RigClone = game.ServerStorage.Rake:Clone()
	game.ReplicatedStorage.PlayerRake.Value = RandomPlayer.Character.Name
	if RandomPlayer.Character then
		print("Player is Rake now!")
		if RandomPlayer.Backpack:FindFirstChild("FirstPerson") then
			RandomPlayer.Backpack.FirstPerson:Destroy()
		end
		RandomPlayer.IsRake.Value = true
		RandomPlayer.CameraMinZoomDistance = game.StarterPlayer.CameraMaxZoomDistance
		RigClone.Parent = workspace
		RigClone:SetPrimaryPartCFrame(RandomPlayer.Character.PrimaryPart.CFrame)
		RigClone.Name = RandomPlayer.Character.Name
		RandomPlayer.Character:Destroy()
		RandomPlayer.Character = RigClone
		RandomPlayer.Character:MoveTo(workspace.CavePart.Position)
		for _,tool in pairs(game.ReplicatedStorage.RakeTools:GetChildren()) do
			if tool:IsA("Tool") then
				tool:Clone().Parent = RandomPlayer.Backpack
			end
		end
		game.ReplicatedStorage.ChangeCam:FireClient(RandomPlayer, RandomPlayer.Character.NPC)
		game.ReplicatedStorage.ToggleRakeVision:FireClient(RandomPlayer, true)
		workspace.DayNightFunction.Value = 1
		wait(5)
		workspace.DayNightFunction.Value = 0
	else
		warn("No character detected!")
		return DayNight()
	end
	if RandomHunter then
		for _,tool in pairs(game.ReplicatedStorage.HunterTools:GetChildren()) do
			if tool:IsA("Tool") then
				tool:Clone().Parent = RandomHunter.Backpack
			end
		end
	end
	wait(200)
	workspace.Day.Value = true
	workspace.RakeDay:Play()
	game.ReplicatedStorage.ToggleRakeVision:FireClient(RandomPlayer, false)
	Day:Play()
	local FakeRake = game.ServerStorage.FakeRake:Clone()
	RandomPlayer.IsRake.Value = false
	RandomPlayer.CameraMinZoomDistance = game.StarterPlayer.CameraMinZoomDistance
	FakeRake.Parent = workspace
	FakeRake:SetPrimaryPartCFrame(RandomPlayer.Character.HumanoidRootPart.CFrame)
	FakeRake.FakeNPC.WalkSpeed = 30
	RandomPlayer:LoadCharacter()
end

ignore is player object that needs to be ignored, get random player but not the same player any time.

Can’t you do?

function GetPlayer(ignore)
	local Players = game.Players:GetPlayers()
	local RandomPlayer = Players[math.random(1, #Players)]
	if RandomPlayer then
		if RandomPlayer.Name ~= ignore.Name then
			return RandomPlayer
		else
			return GetPlayer(ignore)
		end
	end
end

So if the randomPlayer in the function is the same as the ignore, then it runs it again with the ignore player. I believe your issue is that if the player is the same one in that function, it returns the function but without an ignore parameter, so it would try to get the name of nil, which errors

You can just remove all players that’s supposed to be ignored in the Players table and then just randomly pick the players, that should help.

An example would be

function GetRandomPlayer(Ignore)
	local Players = game:GetService("Players"):GetPlayers()
	
	for i, v in pairs(Players) do
		if v.Name == Ignore.Name then
			table.remove(Players, i)
		end
	end
	
	local RandomPlayer = Players[math.random(1, #Players)]
	
	if RandomPlayer then
		return RandomPlayer
	end
end
1 Like

I really dont like using tables, they are hard to use.

Well the Players is a table, meaning you’d still have to work with it inorder to get it to work.

1 Like

It’s best to avoid a recursive function and “hoping the computer gets lucky” as these can degrade script performance. If one player joins your game and the GetPlayer() function is called this whole script will break because you would have just triggered an infinite loop.

I’m just mentioning this since having a function call itself is bad practice. The code @ThunderFrost0001 provided is a much better way to handle this.

2 Likes

i will make it there needs to be at least 2 players in game

Well, if you’re going to use iterative functions at least have a point in your code to yield so it doesn’t risk crashing… Even with 2 players in game you still risk it crashing because you’re just hoping your code picks the right number.

2 Likes

You could use a table instead of this, but since you don’t like using them, you can use it as parameters instead as shown in this example :

function GetRandomPlayer(Ignore, Ignore2)
	local Players = game:GetService("Players"):GetPlayers()
	
	for i, v in pairs(Players) do
		if v.Name == Ignore.Name then
			table.remove(Players, i)
		elseif v.Name == Ignore2.Name then
            table.remove(Players, i)
        end
	end
	
	local RandomPlayer = Players[math.random(1, #Players)]
	
	if RandomPlayer then
		return RandomPlayer
	end
end
1 Like

How do i use yield? i never heard about it

wait(3) = yields the code for 3 seconds.

Can i yield it for 0.1 seconds?

Yeah that works too, as long as you have two or more players then a yield isn’t even necessary but adding a 0.1 second yield would be safer.

can i ask last question, how do i check if there are more than 2 players in game?