Game stops awarding me points at 4 Points thinking that I left the zone even tho I am still in it

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve?

I want to achieve that the game awards points if I am inside the zone and stops awarding me points if I am outside the zone

  1. What is the issue?

Game thinks that I went outside the Zone twice and stops awarding points at 4 points

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?

I couldn’t find solutions similar to this.

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!

local Players = game:GetService("Players")
local Zone = require(game:GetService("ReplicatedStorage").Zone)
local PointGiver = workspace.PointGiver15x
local zone = Zone.new(PointGiver)
local connection


local function givePoints()
	while true do
		wait(1)
		print(1)
		local Playerlist = Players:GetPlayers()
		print(2)
		for currentPlayer = 1, #Playerlist do
			print(3)
			local player = Playerlist[currentPlayer]
			print(4)
			local points = player.leaderstats.Time
			print(5)
			points.Value = points.Value + 2
			print(6)
		end
		
		if zone.playerExited then
			connection:Disconnect()
			print(7)
		end
	end
end

connection = zone.playerEntered:Connect(givePoints)
print(8)
3 Likes

You will need several adjustments to the script but the main error is the misuse of the playerExited connection.

This is not a bool value but an event, it will always be true since it returns the playerExited signal/event like part.Touched.

You should use a seperate event to do so.

local function stopGivingPoints(playerExited)
--find a way to stop giving points to this player exited within this function
end
connection = zone.playerExited:Connect(stopGivingPoints)

Additionally to stop a while true do loop from running externally you can use this technique:

Or you can use a Heartbeat connection which runs every frame to give points everyframe, then :Disconnect() it once the player has left the zone.

I’ve once tried to do that but I couldn’t find a way for it to stop giving the player points so, my only option was :Disconnect()

could you tell me how this zone and Zone works?

I’m using ZonePlus which is more advanced than .Touched and .TouchEnded

Here is the script with the proposed changes I said earlier.

local Players = game:GetService("Players")
local Zone = require(game:GetService("ReplicatedStorage").Zone)
local PointGiver = workspace.PointGiver15x
local zone = Zone.new(PointGiver)

local whoIsGettingPoints = {}--store the cancel givePoints function in a dictionary

local function givePoints(player : Player)--zone+ gives the player instance here
    local givePoints = true
    task.spawn(function()
    	while givePoints do
            task.wait(1)
            local points = player.leaderstats.Time
            print(5)
            points.Value = points.Value + 2
        end
    end)

    whoIsGettingPoints[player] = function()--add a function to set givePoints to false to stop giving points
        givePoints = false
    end
end

local function stopGivingPoints(player : Player)--zone+ gives the player instance here
    local stopGivingPointsFunction = whoIsGettingPoints[player]
    if stopGivingPointsFunction then
        stopGivingPointsFunction()--execute stop giving points
        whoIsGettingPoints[player] = nil
    end
end


zone.playerEntered:Connect(givePoints)
zone.playerExited:Connect(stopGivingPoints)

I am kinda new to scripting and don’t fully understand the dictionary line, could you please explain this to me?

It stores the cancel function for the giving points function.

local whoIsGettingPoints = {}--Initially empty
--then when a player enters
    whoIsGettingPoints[player] = function()--add a function to set givePoints to false to stop giving points
        givePoints = false
    end
--Let's say you entered the dictionary will be this:
whoIsGettingPoints = {
["zygote4593"] = function() givePoints = false end
}
--then it is executed when player has exited
    local stopGivingPointsFunction = whoIsGettingPoints["zygote4593"]
    if stopGivingPointsFunction then
        stopGivingPointsFunction()--execute stop giving points
        whoIsGettingPoints[player] = nil --set to nil to cleanup
    end

But i want everyone to recieve points whenever the enter the zone.

Oh I thought you wanted something like a +1 points to player if in danger zone kinda thing.

It’s still the same concept store a method to cancel the “givingpoints” in a variable or a dictionary (for multiple players no the case here) then execute it when player exited

local Players = game:GetService("Players")
local Zone = require(game:GetService("ReplicatedStorage").Zone)
local PointGiver = workspace.PointGiver15x
local zone = Zone.new(PointGiver)

local givePointsToAllPlayers

local function givePoints() --zone+ gives the player instance here
	local givePoints = true
	task.spawn(function()
		while givePoints do
			task.wait(1)
			local Playerlist = Players:GetPlayers()
			print(2)
			for currentPlayer = 1, #Playerlist do
				print(3)
				local player = Playerlist[currentPlayer]
				print(4)
				local points = player.leaderstats.Time
				print(5)
				points.Value = points.Value + 2
				print(6)
			end
		end
	end)

	if givePointsToAllPlayers == nil then
		givePointsToAllPlayers = function() --add a function to set givePoints to false to stop giving points
			givePoints = false
		end
	end
end

local function stopGivingPoints(player: Player) --zone+ gives the player instance here
    if givePointsToAllPlayers then
        givePointsToAllPlayers()
        givePointsToAllPlayers = nil
    end
end

zone.playerEntered:Connect(givePoints)
zone.playerExited:Connect(stopGivingPoints)

Okay, this is an entirely different way of doing this, but it’s the most efficient(at least I think it is).

local RunService = game:GetService("RunService")
local Zone = game.Workspace.Zone
local Deley = tick()

Zone.Touched:Connect(function()end)

RunService.Stepped:Connect(function() -- using runserivce is much better since even if there is an error, it wont stop.
	if tick() - Deley >= 1 then -- checking if it's been one second since the first time we set deley.
		Deley = tick() -- reset the deley
		local AlreadyTouchedPlayers = {}
		for _, Part in pairs(Zone:GetTouchingParts()) do
			local Player = game.Players:GetPlayerFromCharacter(Part.Parent) -- getting the player
			if Player and not table.find(AlreadyTouchedPlayers, Player) then -- if the player exist, and if you havent touched the same player's part twice then continue
				AlreadyTouchedPlayers[#AlreadyTouchedPlayers + 1] = Player
				Player.leaderstats.Time.Value += 1 -- add the score
			end
		end
	end
end)

sorry for the late reply but this actually worked! Thank you for teaching me <3

This should work, however the issue is that it could be less efficient than zone+ under a certain scenario the reason is because it uses :GetTouchingParts() which can detect parts that are not the player like the buildings, accessories, and tools.

Thanks for trying to help out as well though, appreciate it.

that’s why I used

local Player = game.Players:GetPlayerFromCharacter(Part.Parent)

to make sure the part is a character’s bodypart

Hey, idk if you’re gonna reply but… when there is 2 or more people in game, and one person enters the zone, everyone gets points, i wanted that when player enters the zone, they only get points. not others.

Thats what you said though.

Then use the other one

I’m very sorry that I said that, but thank you it worked! :smiley: