Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

Touched Event doesn't fire when player jumps across it?

I am making an obby and have a very simple script that teleports the player back to a spawnObject when they touch the lava. Here it is:

local Players = game.Players
local lava = script.Parent
local spawnObject = lava.Spawn.Value

lava.Touched:Connect(function(part)
	print("Touched")
	for i, v in ipairs(Players:GetChildren()) do
		pcall(function()
			local char = v.Character
			if part:IsDescendantOf(char) then
				char:MoveTo(spawnObject.Position)
			end	
		end)
	end
end)

This script is in the block of lava and the block of lava has an ObjectValue in it named "Spawn" which is set to the value of a spawnlocation block.

It functions correctly but fires inconsistently. If the player walks across the lava it will work fine, but the player can easily jump across the block and it won't get fired unless the player stops jumping while still on the block. This is a problem because if the player jumps on the lava they can easily reach the end.

Is there a way to make it fire even though the player is jumping?

PS (I know I haven't added a debounce yet)

EDIT: I have also tried connecting the touched event from the player and no luck:

local Players = game.Players
local lava = script.Parent
local spawnObject = lava.Spawn.Value

Players.PlayerAdded:Connect(function(plr)
	spawn(function()
		while wait(1) do
			local char
			pcall(function()
				char = plr.Character
				char.Humanoid.Touched:Connect(function(part)
					if part == lava or part:isDescendantOf(lava) then
						char:MoveTo(spawnObject.Position)
					end	
				end)
			end)
			plr.CharacterAdded:Wait()
		end
	end)
end)

2 answers

I have managed to figure out a solution using rays. Apparently, humanoids can make the character jump before it actually ever touches the part. By using a ray that's length is the character's height + the amount the humanoid can hover over a part and still jump it works around this. I found this out from this

Here is my finished code. The 5 can be reduced to something like 4.75 or 4.5 or even down to 3 if it is a tad too big. I found that 3 fit my needs pretty well.

local Players = game.Players
local lava = script.Parent
local spawnObject = lava.Spawn.Value

Players.PlayerAdded:Connect(function(plr)
	spawn(function()
		while wait(1) do
			local char
			local runServBind
			pcall(function()
				char = plr.Character
				runServBind = game["Run Service"].Stepped:Connect(function()
					local part = workspace:FindPartOnRay(Ray.new(char.HumanoidRootPart.Position,Vector3.new(0,-5,0)),char)
					if part then
						if part == lava or part:IsDescendantOf(lava) then
							char:MoveTo(spawnObject.Position)
						end
					end
				end)
			end)
			plr.CharacterAdded:Wait()
			runServBind:Disconnect()
		end
	end)
end)

I then added the touched event for the sides to trigger it as well.

lava.Touched:Connect(function(part)
	print("Touched")
	for i, v in ipairs(Players:GetChildren()) do
		pcall(function()
			local char = v.Character
			if part:IsDescendantOf(char) then
				char:MoveTo(spawnObject.Position)
			end	
		end)
	end
end)

A few debounces, comments, and fixes later and this was my finishing product:

local Players = game.Players
local lava = script.Parent
local spawnObject = lava.Spawn.Value --The object the player should teleport to

local debounce = {checked=false,teleported=false} --This will handle advanced debouncing
--It will make sure that both Touched and Ray check for touched but only one teleports.
function teleportIfTouch(char)
	local part = workspace:FindPartOnRay(Ray.new(char.HumanoidRootPart.Position,Vector3.new(0,-3,0)),char) --Gets a part if there is one on the ray
	--Checks there is a part and then if the part is the lava or apart of the lava
	if part then
		if part == lava or part:IsDescendantOf(lava) then
				if (debounce.checked == false or (debounce.checked == true and debounce.teleported == false)) and not(debounce.checked == true and debounce.teleported == true) then
					debounce.checked = true
					debounce.teleported = true
					--Moves the character
					char:MoveTo(spawnObject.Position)
					wait(0.1)
					debounce.checked = false
					debounce.teleported=false
				end
		end
	end
end
--HANDLES TOUCHING LAVA USING RAYS (MORE PERCISE) [Prevents jumping over lava]
Players.PlayerAdded:Connect(function(plr)
	while wait(1) do
		local char --Will hold the character
		local runServBind --Will hold the runServince.Stepped Bind
		local runServBind2
		local runServBind3
		local unspawn = false --Will handle wether the spawn can be disabled
		pcall(function()
			char = plr.Character
			spawn(function()
				while wait() do
					teleportIfTouch(char)
					if unspawn then
						break
					end
				end
			end)
			runServBind = game["Run Service"].Stepped:Connect(function() --This will run every frame prior to physics simulation update
				teleportIfTouch(char)
			end)
			runServBind2 = game["Run Service"].Heartbeat:Connect(function() --This will run every frame prior to physics simulation update
				teleportIfTouch(char)
			end)
			runServBind3 = game["Run Service"].RenderStepped:Connect(function() --This will run every frame prior to physics simulation update
				teleportIfTouch(char)
			end)
		end)
		--Waits for the character to be added and disconnects the event
		plr.CharacterAdded:Wait()
		unspawn = true
		runServBind:Disconnect()
		runServBind2:Disconnect()
		runServBind3:Disconnect()
		--The next loop will get the new character and repeat.
	end
end)

--When the lava is touched
lava.Touched:Connect(function(part)
	
		for i, v in ipairs(Players:GetChildren()) do --Loop through all players
			--Checks if part is apart of the player's character
			--pcall(function()
				local char = v.Character
				if part:IsDescendantOf(char) then
					if (debounce.checked == false or (debounce.checked==true and debounce.teleported == false)) and not(debounce.checked == true and debounce.teleported == true) then
						debounce.teleported = true
						debounce.checked = true
						--Moves the character
						char:MoveTo(spawnObject.Position)
						wait(0.3)
						debounce.checked = false
						debounce.teleported = false
					end
				end	
			--end)
		end
end)

#edit: fixed dead link in post

1 comment

0

A simpler solution than using rays is to have an invisible block set to CanCollide false above the lava and put the touched event on this block instead of the lava.

The problem is that you're applying :MoveTo function to the character object itself which is a model and doesn't have a position property.

To make the script work change this line

char:MoveTo(spawnObject.Position)

to this one:

char:SetPrimaryPartCFrame(spawnObject.CFrame)

EDIT: Also, the first script you've posted is preferable as the second one seems quite messy and unreliable. And there's no real need to use pcall(), any errors caused within it won't be visible in the console which makes it harder to figure out what the problem is. Here's a way to avoid any errors if there's currently no character for a given player in the workspace:

local Players = game.Players
local lava = script.Parent
local spawnObject = lava.Spawn.Value
 
lava.Touched:Connect(function(part)
	for i, v in ipairs(Players:GetChildren()) do
		local char = v.Character

		--this makes sure that char exists
		if char then		
			if part:IsDescendantOf(char) then
				char:SetPrimaryPartCFrame(spawnObject.CFrame)
			end
		end
	end
end)

3 comments

0

This is not the reason as the touched event is not firing at all when the player jumps. Anything within the touched event wouldn't matter as it is the touched event itself that is having issues. Plus MoveTo does work on Models. If I said Model.Position that woudn't work. MoveTo is a valid function of Models and is actually an alternative to SetPrimaryPartCFrame and Position for Parts.

0

Oh, really? My bad then. Lemme see what else could cause the problem eh

0

I've found a solution

This discussion is preserved as it was. New answers, comments, and votes are closed.