Touched events fire at a distance of 300+ studs in studio

I ran into a sticky situation. I have an obby checkpoint server script that listens for touched events and stores information about latest checkpoint.

The issue is sometimes a touched event will fire in studio, for a previous checkpoint while the player is 300 studs away from the checkpoint. For example, I am in stage 37 and a touched event fires for the stage 31 checkpoint. This happens fairly frequently when I playtest in studio, example below.

I tried adding a breakpoint in the checkpoint script, but the breakpoint doesn’t “fire” even if the print statement where it is located does execute. I also tried printing out information and play the obby to see if I can determine what happens. Only thing I can figure out is it seems a touched event sometimes fires not when supposed to. Possible at a later time in conjunction with another touched event. Or maybe it double-fires.

I checked developer site, but I cannot find anything in the developer sites about rate limits for part.Touched events. General touch event performance is good, as I can see when I walk over a stage where touched events are used to trigger tween of transparency of parts then the player steps on them. There is no noticeable lag in studio for that.

This is how the touched event function looks. Excuse all the extra code, but you get the idea.

local Players=game:GetService("Players")
local ReplicatedStorage=game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")

local playerData = require(ServerStorage.Scripts.PlayerDataModuleScript)
local ObbyModule = require(ReplicatedStorage.Scripts.Obby)
local BadgeModule = require(ServerStorage.Scripts.BadgeModuleScript)

local obbyName=script:FindFirstAncestorOfClass("Model").Parent.Parent:GetAttribute("ObbyID")
local stageName=script:FindFirstAncestorOfClass("Model").Name

local checkpoint=script.Parent
local obbyPart=checkpoint.Parent.Parent

script.Parent.Touched:Connect(function(touchingPart)
	local character=touchingPart:FindFirstAncestorOfClass("Model")
	if character then
		if (checkpoint.Position-touchingPart.Position).Magnitude>20 then
			warn("touching at distance " .. (checkpoint.Position-touchingPart.Position).Magnitude)
		end
		local player=Players:GetPlayerFromCharacter(character)
		if player and (player:GetAttribute("ObbyID")~=obbyName or player:GetAttribute("StageName")~=stageName) then
			-- do not allow player to activate previous checkpoints, since touch events can seemingly be significantly delayed (?)
			if tonumber(stageName)>=tonumber(player:GetAttribute("StageName") or 0) then
				--print("checkpoint ok:" .. obbyName .. " - " .. stageName .. " pos=" .. tostring(script.Parent.Position+Vector3.new(0,3,0)))
				-- checkpoint is further than max progress
				player:SetAttribute("ObbyID",obbyName)
				player:SetAttribute("StageName",stageName)
				character:SetAttribute("CheckpointPos",script.Parent.Position+Vector3.new(0,3,0))
				local obby=ObbyModule.getObby(obbyName)
				ReplicatedStorage.Events.SkyBox:FireClient(player,ObbyModule.skyBoxes[obby.skyBox].Name)
				if obbyName==tostring(player.UserId) then
					-- player's own obby, enable UI
					ReplicatedStorage.Events.StageMoveGUISetState:FireClient(player,tonumber(stageName),#obbyPart:GetChildren(),true,true,true)
					task.wait()
				else
					if string.sub(obbyName,1,5)=="Robot" then
						-- weekly obby, enable UI
						ReplicatedStorage.Events.StageMoveGUISetState:FireClient(player,tonumber(stageName),#obbyPart:GetChildren(),true,true,false)
						-- if touching a new checkpoint in the weekly obby, save the progress if higher than previous max stage reached
						local playerMaxStage=playerData.GetPlayerValue(player,obbyName)
						if not playerMaxStage or tonumber(playerMaxStage)<tonumber(stageName) then
							playerData.SetPlayerValue(player,obbyName,stageName,false)
							playerMaxStage=stageName
						end
					else
						-- other player's obby - award a badge to both, if they are friends
						local obbyUser=tonumber(obbyName)
						if player:IsFriendsWith(obbyUser) then
							BadgeModule.awardBadge(player,2145029312,"rbxassetid://13318482662","rbxassetid://1836442563")
							local obbyUserPlayer=Players:GetPlayerByUserId(obbyUser)
							if obbyUserPlayer then
								BadgeModule.awardBadge(obbyUserPlayer,2145029312,"rbxassetid://13318482662","rbxassetid://1836442563")
							end
						end
						-- does not save progress for obby of other players ---- how would we know if the obby had changed unless we introduce versioning upon deleting stages
					end
				end
			else
				-- player touched a previous checkpoint
				print("checkpoint regression:" .. obbyName .. " - " .. stageName .. " pos=" .. tostring(script.Parent.Position+Vector3.new(0,3,0)) .. " parent: " .. checkpoint.Name)
				--print("distance primary" .. (character.PrimaryPart.Position-script.Parent.Position).Magnitude)
				print("distance touching " .. (touchingPart.Position-script.Parent.Position).Magnitude)
			end
		end
	end
end)

This is the not-breaking-breakpoint:

image

This is how a bogus touched event looks in the output:

I also tried printing out the player character’s bounding box to determine if there was a problem with the model. I believe the last three numbers are the size. There is no way the model should touch a checkpoint up to 300 studs away.

  17:44:37.733  > print(workspace.solsort500:GetBoundingBox())  -  Studio
  17:44:37.734  1085.28833, 217.104767, 563.436401, -0.544371188, 7.52759277e-08, -0.838844419, -1.72823214e-08, 1, 1.00953073e-07, 0.838844419, 6.94531224e-08, -0.544371188 3.4068899154663086, 5.433774948120117, 3.1484203338623047  -  Client

PS: My workaround is to not accept any checkpoint as the latest, if it has a lower number than the previous. So I am good, I just have no clue how this could happen. Do you think this would qualify as a bug report in the “studio-performance-examples” that were recently requested?

This probably has to do with an accessory a body part or a tool.
Please select your character inside the game when it happens. It should be about 5x4x1, big.
If it’s bigger than it’s supposed to look for any part which is not directly attached to the player.

When I select the model, I don’t see its size anywhere. But I get this:

Funny thing about the broken breakpoint: I made one in the other branch of the “if” statement, the one that normally gets executed instead of the else clause - and I got dropped into the debugger the exact time when I touched a checkpoint.

I just tried closing studio and opening it again. It still happens. So I did this:

image

Just to get a stack dump and look for anything interesting. But nothing informative came out of that.

I am in the beta studio, but I have this one enabled:

image

It should be the old one, right? Tried switching to deferred event handling, same thing still happens.

However, I have become better at reproducing it. And a lot better at playing my obby game. :rofl:

It seems I need to jump from a checkpoint quickly (within about 1 second) onto another part in next stage, that has a touched event connected. Like I have a stage with elevators, for example. That will cause something to happen that seems to look like an old touched event that re-fires, from maybe 1-2 minutes before.

Is there a problem with calling something async like saving player progress to a datastore within an event handler for part touched event? I sense this will be a long process of elimination for me. :slight_smile:

Well honestly I am not quite sure how to make it work then instead, what I’d suggest doing is 1 of 2 things.

  1. Detect .Touched SS, check magnitude from checkpoint to character
  2. Detect .Touched CS, fire remoteEvent to SS, check magnitude from checkpoint to character

And have the magnitude be enough to just touch the edge and also enough for players with about 500 ms latency.

1 Like

So, now this is where I am at:

image

Ok, I will relaunch studio. I have a breakpoint here:

So, studio drops into the debugger when I step on the first checkpoint and the touched event is fired. Nothing is in the output window. Ergo the code just before the breakpoint did not execute. The problem is now the opposite from before: The breakpoint was not hit, but studio drops into the debugger.

I will try again tomorrow after a reboot and a good night’s sleep. Also it’s 8:30 PM - time to eat. :grimacing: