Safe zone error

Okay so, I was trying to create a Safe zone and It work at first code but it was firing remotes way too much since it works everytime a player’s part leaves or enters area And it will probably makes server too laggy so I Tried to use second code which takes just humanoid but it gave an
error 19: attempt to index nil with ‘Humanoid’
FirstCode

local SafeZone = script.Parent
local CframeOfBox = SafeZone.CFrame
local SizesOfBox = SafeZone.Size
local CollectionService = game:GetService("CollectionService")
local players = game:GetService("Players")
local replicatedStorage = game:GetService("ReplicatedStorage")
local remotes = replicatedStorage:WaitForChild("Remotes")


local function Check(player)
	local PlayerIsInTheZone =  false
	local InsideOfTheZoneParts = workspace:GetPartBoundsInBox(CframeOfBox,SizesOfBox,nil)
	for _, i in pairs(InsideOfTheZoneParts) do
		if i.Parent.Name == player.Name then
			PlayerIsInTheZone = true
			break
		end
	end
	local Character = player.Character
	if Character then
		if PlayerIsInTheZone then
			CollectionService:AddTag(Character, "SafeZone")
		else
			CollectionService:RemoveTag(Character,"SafeZone")
		end
	end
	if CollectionService:HasTag(Character,"SafeZone") then
           print("TestNumber2")
		remotes.SafeZone:FireClient(player)
	end
	
	CollectionService:GetInstanceRemovedSignal("SafeZone"):Connect(function(Character)
		print("TESTNUMVER1")
		remotes.SafeZone:FireClient(player)
	end)

end

while true do
	wait(.2)
	for i , v in pairs(players:GetChildren()) do
		Check(v)
	end
end

in SecondCode the only changes I did is trying to getting Humanoid and Changing “Character” variables to “Hum”
SecondCode=

local SafeZone = script.Parent
local CframeOfBox = SafeZone.CFrame
local SizesOfBox = SafeZone.Size
local CollectionService = game:GetService("CollectionService")
local players = game:GetService("Players")
local replicatedStorage = game:GetService("ReplicatedStorage")
local remotes = replicatedStorage:WaitForChild("Remotes")


local function Check(player)
	local PlayerIsInTheZone =  false
	local InsideOfTheZoneParts = workspace:GetPartBoundsInBox(CframeOfBox,SizesOfBox,nil)
	for _, i in pairs(InsideOfTheZoneParts) do
		if i.Parent.Name == player.Name then
			PlayerIsInTheZone = true
			break
		end
	end
	local hum = player.Character.Humanoid -- Error points is here
		if hum then
		if PlayerIsInTheZone then
			CollectionService:AddTag(hum, "SafeZone")
		else
				CollectionService:RemoveTag(hum,"SafeZone")
			end
			
	end
	if CollectionService:HasTag(hum,"SafeZone") then
		remotes.SafeZone:FireClient(player)
	end
	
	CollectionService:GetInstanceRemovedSignal("SafeZone"):Connect(function(hum)
		print("TESTNUMVER1")
		remotes.SafeZone:FireClient(player)
	end)

end

while true do
	wait(.2)
	for i , v in pairs(players:GetChildren()) do -- and here
		Check(v)
	end
end

You are connecting this function infinite times:

	CollectionService:GetInstanceRemovedSignal("SafeZone"):Connect(function(Character)
		print("TESTNUMVER1")
		remotes.SafeZone:FireClient(player)
	end)

Connecting the same function many times during an event will cause to have multiple functions running, and multiple calls to the remote.

Follow this:
Theres 2 players in ther server

while true do
	wait(.2)
	for i , v in pairs(players:GetChildren()) do
		Check(v)

Each 0.2 secs, you are calling Check() two times, cause theres 2 players
Each time Check() runs, its connecting/creating a new function which is firing the remote:

CollectionService:GetInstanceRemovedSignal("SafeZone"):Connect(function(Character)
		print("TESTNUMVER1")
		remotes.SafeZone:FireClient(player)
	end)

So in only one second of your script running, you have 5 functions firing the remote for the same player, multiple stacked functions.

Take out that connection from the Check() make sure you are connecting that only once, and if needed disconnect it

1 Like

Okay, I understand why problem is occurring but I am pretty stupid about solving parts
I removed this function from the Check()

CollectionService:GetInstanceRemovedSignal("SafeZone"):Connect(function(Character)
		print("TESTNUMVER1")
		remotes.SafeZone:FireClient(player)
	end)

but then it said

Unknown global "player"

so I changed


CollectionService:GetInstanceRemovedSignal("SafeZone"):Connect(function(Character)
		print("TESTNUMVER1")
		remotes.SafeZoneExit:FireClient(player) -- Here

to


CollectionService:GetInstanceRemovedSignal("SafeZone"):Connect(function(player)
		print("TESTNUMVER1")
		remotes.SafeZoneExit:FireClient(player)

But then that error occured


I already defined player argument? or I didn’t ?

second issue is how can I connect Check() 1 time for every player even there is a 2 player or more?

because even I remove that function
this remote event

		end
	end
	if CollectionService:HasTag(Character,"SafeZone") then
		remotes.SafeZone:FireClient(player)
		print("PlayerIsInSafeZone")
	end	
end

will still fire 10 times if there are 2 player in the safe zone and it is bad, should I remove that part from the Check() function too and use CollectionService:GetInstanceAddedSignal ?

That’s because the only time you define player is as a parameter of the check function.

Changing in itself this won’t do anything. That isn’t a player object, that’s a humanoid, from what I can see in your script. You can however, get the player from that, using game.Players:GetPlayerFromCharacter(hum.Parent)

Yes.

1 Like

well I can’t use hum.parent because this time it will probably say unknown global “hum” since hum is only defined as a parameter in the check function I can’t test because I am not in home or close to pc. but it won’t probably

btw I am currently using 1st script With “Character” not “hum” since peashie said problem is not with number of player parts well won’t make any chance probably just want to say to avoid confusion

thanks for that by the way,

1 Like

It’s not.
Just change the parameter from player in the GetInstanceRemovedSignal to hum or humanoid for less confusion. Judging by your script, the only thing that parameter will ever be is a humanoid.

1 Like

Okay rightnow I am really feeling deeply embrassed and stupid to still not able to fix it and asking for it but this is the whole code

local SafeZone = script.Parent
local CframeOfBox = SafeZone.CFrame
local SizesOfBox = SafeZone.Size
local CollectionService = game:GetService("CollectionService")
local players = game:GetService("Players")
local replicatedStorage = game:GetService("ReplicatedStorage")
local remotes = replicatedStorage:WaitForChild("Remotes")


local function Check(player)
	local PlayerIsInTheZone =  false
	local InsideOfTheZoneParts = workspace:GetPartBoundsInBox(CframeOfBox,SizesOfBox,nil)
	for _, i in pairs(InsideOfTheZoneParts) do
		if i.Parent.Name == player.Name then
			PlayerIsInTheZone = true
			break
		end
	end
	local Hum = player.Character.Humanoid 
	if Hum then
		if PlayerIsInTheZone then
			CollectionService:AddTag(Hum, "SafeZone")
		else
			CollectionService:RemoveTag(Hum,"SafeZone")
		end
	end
	
end
local player =game.Players:GetPlayerFromCharacter(Hum.Parent) -- Unknown Global hum error here




CollectionService:GetInstanceAddedSignal("SafeZone"):Connect(function(Hum)
	print("TestNumber1")
	remotes.SafeZone:FireClient(Hum)
end)

CollectionService:GetInstanceRemovedSignal("SafeZone"):Connect(function(Hum)
	print("TESTNUMVER1")
	remotes.SafeZoneExit:FireClient(Hum)
end)


while true do
	wait(.2)
	for i , v in pairs(players:GetChildren()) do
		Check(v)
	end
end

and if I place this part of code to inside of check() function

local player =game.Players:GetPlayerFromCharacter(Hum.Parent) 

then
it gives error here

local Hum = player.Character.Humanoid -- index nil with "Humanoid"
1 Like

Another alternative is to use ZonePlus .It’s useful module to detect if a player entered a part or left a part.

Have a look:

After grabbing the module put it in ReplicatedStorage and name it “Zone” and drop this code into your script.


local Zone = require(game:GetService("ReplicatedStorage").Zone)
local SafeZone  = -- PATH TO YOUR SAFEZONE PART
local zone = Zone.new(container)

zone.playerEntered:Connect(function(player)
   -- Let the player be safe, he entered the safe zone.
end)

zone.playerExited:Connect(function(player)
    -- Let the Player not be safe anymore, he left the safe zone.
end)
2 Likes

Don’t feel embarrassed at all! This is part of the process.

You should be putting this in the GetInstanceAdded and GetInstanceRemoved functions, you already have the player as a parameter in check().

1 Like

Yeah, this is definitely a great alternative.

1 Like


The output still asks me what the hell is Humanoid

Yeah I have seen ZonePLus before but Idk why I am not using it maybe because of that ForceField pop up or I hate the idea of using someone else is code or maybe A part of myself wants to learn how to do it with mistakes
I really don’t know the reason well since many people are using it, it is probably safe but still I don’t want to use it but thanks for advice

I bet since this is always running, it runs before the character is loaded, and thus Humanoid doesn’t exist, which is supported by the error.
Try changing Line 19 to

local Hum
if player.Character then
    Hum = player.Character:WaitForChild("Humanoid")
else
    return
end
1 Like

Thanks! it is working now!
30 thing

1 Like

Awesome!
Also, I’m just realizing now that in your script you have an if statement to check for Hum, so you can either get rid of that or get rid of the “else return” when you set Hum, and it should still work.

1 Like

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