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:
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?