One time collectible only able to be picked up by one player

Hello! For my game, I am implementing a system commonly found in other Roblox games where there are collectibles around the map. I want each player to individually be able to collect the item ONCE and no more than that.

The above statement I have achieved when dealing with a single player. The problem is that nobody else is able to collect the item after the one player has obtained it. Video below. (Watch the point counter go from 500 to 550)


I believe the system that I have begun to put in place is on the right track but I am missing a thing or two. Whenever the player interacts with the collectibles hitbox, a tag gets added to their player that checks that they have collected the item and if they have said tag, the item cannot be picked up anymore and this works great… until the other player isn’t able to get the tag.

What check do I need to add? Or is there an entirely better way to do it? I’ll leave the entire collectible script below.

local tweenService = game:GetService("TweenService")
local players = game:GetService("Players")
local collectiblesFolder = game.Workspace.Collectibles
local collectiblesTable = collectiblesFolder:GetChildren()

local function gems()

	for _, gem in pairs (collectiblesTable) do

		local hitbox = gem:WaitForChild("Hitbox")
		local primaryPart = gem:WaitForChild("CenterPart")
		
		--Styling information. Not apart of the problem.
		local gemTweenInfo = TweenInfo.new(1, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, -1, true, 0)
		local gemTweenProperties = {
			["CFrame"] = CFrame.new(primaryPart.Position) + Vector3.new(0,5,0)
		}
		local gemTween = tweenService:Create(primaryPart, gemTweenInfo, gemTweenProperties)

		gemTween:Play()
		----------------------------------------------------
		local collectedTag = Instance.new("BoolValue")
		collectedTag.Name = "Collected "..gem.Name
		collectedTag.Value = false
		
		hitbox.Touched:Connect(function(otherPart)
			
			local player = players:GetPlayerFromCharacter(otherPart.Parent)
			local humanoid = otherPart.Parent:FindFirstChild("Humanoid")
			
			if player and humanoid then
				
				collectedTag.Parent = player
				
				if collectedTag.Value == false then
					collectedTag.Value = true
					player.leaderstats.Points.Value += 50
					print("touched")
				end
			end
		end)
	end
end

gems()
1 Like

I can easily help you with this. The reason this is happening is because you are only instancing the boolean value one time into the game and once it is parented to the player there is no new creations of boolean values because the original is now being stored in the player who collected it. Instead we will use proper checks to instance one boolean value into each player and you can modify the value of each boolean value inside of each player to your liking.

local collectedTag = Instance.new("BoolValue")

collectedTag.Name = "Collected"

collectedTag.Value = false --whatever value you want

script.Parent.Touched:Connect(function(otherPart) --script.Parent is just because I had to put the script inside of the part being touched but you can use it however you want
			
local player = game.Players:GetPlayerFromCharacter(otherPart.Parent)
			
local humanoid = otherPart.Parent:FindFirstChild("Humanoid")
			
if player and humanoid then

if player and not player:FindFirstChild("Collected") then
				
local clone = collectedTag:Clone()
                
clone.Parent = player
                
clone.Value = false --whatever value you want
					
print("touched")
				
end
			
end
		
end)

Ah I always forget about cloning! Just needed a minor touch-up and it worked. Thanks!

1 Like

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