Is it possible to only allow *one* person on a block at once?

I want one person to be allowed on a block at once. When a player steps on, it’ll teleport them to their position, but anyone else who steps on the block after will get teleported to a different position. Someone new wont be able to step on the block until the person on it gets off. I know this seems like an odd idea but it would work perfectly for the project I’m working on.

Current script within the part

script.Parent.Touched:Connect(function(hit)
	local player = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent)
	local humanoidRootPart = hit.Parent:WaitForChild("HumanoidRootPart")
	if debounce == false then --if no one is golfing then
		debounce = true
		humanoidRootPart.Position = Vector3.new(-14.309, 3, -28.708) --XYZ
	elseif debounce == true then
		humanoidRootPart.Position = Vector3.new(-10.857, 3, -19.976) --XYZ
	end
end)

As of now, my current script uses a debounce to see if someone is “using” the block. The issue with it is that it teleports all users off, instead of keeping the original user (which I know). I’m unsure of how to implement these additions to allow one user to stay on the block while it teleports others off.

Currently this script doesn’t check which player is on it, so when the player is touching this block the code will fire again, and since the debounce is true it will teleport the player using it off as well. Instead of using a bool debounce, I would set a variable equal to the character, and then check if the new hit character is equal to the variable.

2 Likes

Put the blocks in a table and count how many times a person has teleported

local amount = 0
local Parts = {
game.Workspace.Part1,
game.Workspace.Part2,
game.Workspace.Part3
}
script.Parent.Touched:Connect(function(hit)
	local player = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent)
	local humanoidRootPart = hit.Parent:WaitForChild("HumanoidRootPart")
	if debounce == false then --if no one is golfing then
               if Parts[amount+1] ~= nil then
               amount = amount + 1
               else
               amount = 1
               end
		debounce = true
		humanoidRootPart.Position = Parts[amount].Position + Vector3.new(0,5,0) --XYZ
	elseif debounce == true then
		humanoidRootPart.Position = Vector3.new(-10.857, 3, -19.976) --XYZ
	end
end)

Something like this, tr and fit as many parts as you want

Or you could just put Vector3 values in the table if you want precision

1 Like

Use Region3 to create a small box surrounding the players feet and check if any bodyparts other than the players are on the part then tp the touching parts humanoidrootpart off the part.

1 Like

Fuse both ideas, @FroggoBLOX said. Store the original character into a variable, and compare if the next characters are not it. And Make a list of positions as @legs_v said.

But you mention the player is “using” the teleporter? So it will be standing there for some amount of time? or gets inmediately teleported? What u mean, dont let 2 characacters standing on the part at the same time? Thats never gonna happen if you teleport them on instant touch event, isnt?

1 Like

For example, if I was on the part, I want it to teleport me to a brick (located on the part) as the golfing position. If you were to step on the part while I’m on it, it would teleport you off, onto a different brick. You wouldn’t be able to step on until I got off.

part.Touched:Connect(function(hit)
	if hit:FindFirstChild("Humanoid") then
		if game:GetService("Players"):GetPlayerFromCharacter(hit.Parent) then
			local raycastParameters = RaycastParams.new()	
			raycastParameters.IgnoreWater = true
			raycastParameters.FilterType = Enum.RaycastFilterType.Blacklist				
			raycastParameters.FilterDescendantsInstances = {hit.Parent}
			local newRaycast = workspace:Raycast(golfingPart.Position,golfingPart.Position+Vector3.new(0,10000,0),raycastParameters)
			if not newRaycast then
				hit.Parent.HumanoidRootPart.CFrame = golfPart.CFrame
			else
				-- code if player is on part
			end
		end	
	end
end)

I think I get you, but a little confusing. If you touch the part, you get teleported to another another part, so u are not standing in that part anymore.

Anyway. It doesnt matter which is touching or not the part, just store the first player into a var, and compare it to see if another one touches it, then tp to a different place

Also make sure to mark a solution.

@112365595, I tried your suggestion with little edits but it doesn’t seem to work. I don’t see any errors in the output at all, it just does nothing.

Edited Script
local debounce = false
local golfingPart = script.Parent.Parent.Parent.GolfPosition
local spectatingPart = script.Parent.Parent.Parent.GolfSpectate

script.Parent.Touched:Connect(function(hit)
	if hit:FindFirstChild("Humanoid") then
		if game:GetService("Players"):GetPlayerFromCharacter(hit.Parent) then
			local raycastParameters = RaycastParams.new()	
			raycastParameters.IgnoreWater = true
			raycastParameters.FilterType = Enum.RaycastFilterType.Blacklist				
			raycastParameters.FilterDescendantsInstances = {nil}
			local newRaycast = workspace:Raycast(golfingPart.Position,golfingPart.Position+Vector3.new(0,10000,0),raycastParameters)
			if not newRaycast then
				hit.Parent.HumanoidRootPart.Position = golfingPart.Position
			else
				hit.Parent.HumanoidRootPart.Position = spectatingPart.Position
			end
		end	
	end
end)

Rip idk whats wrong with the script then sometimes raycasts are buggy like this for me

1 Like

@legs_v If or when you have time, can you help explain your code? It makes sense the way you did it, with adding amounts to determine if someone is on, but what happens when they get off the part? Shouldn’t their amount reset or = 0?

Alternatively you could create a small region on the golfing part and use workspace:FindPartOnRayWithIgnoreList(region3,ignoreList,maxParts) to check if a player is on it.

@112365595 I partially fixed the issue of it not working or printing output errors.

You had: if hit:FindFirstChild("Humanoid") then

It should be: if hit.Parent:FindFirstChild("Humanoid") then

The issue now is that it doesn’t allow the one user to stay on the block without teleporting off seconds after. A clip here: https://gyazo.com/d51850d6646aa8f5550a2fd96eda934f explains what I’m talking about. It only keeps the player on the platform if they have the golf club out, and even then it continuously teleports them.

This is because under the else you set the same humanoidrootparts position to the spectating part.

			hit.Parent.HumanoidRootPart.Position = spectatingPart.Position

Oh, so what you’re saying is I need to find new humanoidrootparts that step on after?

No else is if theres actually somebody standing on the part so you won’t teleport anybody until they get off

Is there anyway to find new humanoidrootparts that step on after that which would be teleported off the mat (to the spectating part) until the player got off the block?

If the player gets off the block then the raycast won’t detect the player and i don’t even think you need the else part since it will only work if theres nobody on the part and thats all we need

So this should be our ending code

part.Touched:Connect(function(hit)
	if hit.Parent:FindFirstChild("Humanoid") then
		if game:GetService("Players"):GetPlayerFromCharacter(hit.Parent) then
			local raycastParameters = RaycastParams.new()	
			raycastParameters.IgnoreWater = true
			raycastParameters.FilterType = Enum.RaycastFilterType.Blacklist				
			raycastParameters.FilterDescendantsInstances = {hit.Parent}
			local newRaycast = workspace:Raycast(golfingPart.Position,golfingPart.Position+Vector3.new(0,10000,0),raycastParameters)
			if not newRaycast then -- if no player is on the part then 
				hit.Parent.HumanoidRootPart.CFrame = golfPart.CFrame -- teleport the player who touched the part
			end
		end	
	end
end)