The .Touched() event seems to fire even when a physical collision should not have been possible. This is uncommon, but happens frequently enough to be reproduceable in a few minutes. Considering how ubiquitously this event is relied on, I strongly urge that the internal mechanisms that handle this event should be re-examined, and that more detailed documentation for what exactly registers as a touch be published.
In my testing, I’ve used the classic sword in the toolbox (I believe originally scripted by Shedletsky, the former Creative Director at Roblox), with the Handle’s Massless set to true, and a set of anchored R6 dummies with an R6 avatar.
I ran my game at the maximum 240 FPS to match the 240hz of the internal physics engine, as enabled by the new FPS switcher, and used a LocalScript with a .Touched() listener on the sword’s handle.
When the event is fired, I immediately store the CFrame of the sword’s handle to save its position before the physics simulation completes, as well as the sword’s CFrame after RunService.PostSimulation:Wait(). Using the deltaTime argument, I ensure the check only happens when PostSimulation is running in-tandem with the physics simulation of 240hz.
With RunService and the physics engine in-sync, only one CFrame could have existed between the sword’s PreSimulation CFrame and it’s PostSimulation CFrame, which I obtain via :Lerp() with an alpha of 0.5.
I then check if the touch was possible by using WorldRoot:GetPartsBoundInBox() on the sword’s PreSimulation CFrame, lerped CFrame, and its PostSimulation CFrame.
Many times .Touched() will fire when none of the three checks are valid. To illustrate this, I also create a clone of the sword’s handle using the stored CFrames:
As you can see, this touch should not have been possible, and yet .Touched() was fired. Even when using WorldRoot:ArePartsTouchingOthers() with an overlapIgnored argument of 0, we can confirm the parts are indeed not touching:
Given this, I am not sure how it was possible for the physics engine to report a touch; I believe it was done in error.
Moreover, documentation for the internal physics engine’s handling of .Touched is still painfully lacking, and a fix, or at least a clarification, would be greatly appreciated and in my opinion, needed.
I’ve attached a copy of the testing place I used below. Note that this seems to happen infrequently, and can take several minutes and a few reloads to occur, but does indeed happen.
TestingTouched.rbxl (66.8 KB)
Testing was done on Roblox Studio version 0.628.0.6280391 (64-bit). I used a Windows 10 PC on version 22H2, build 19045.4412 with an AMD Ryzen 5800X, an NVIDIA RTX 3070, and 32 GB of DDR4 3600Mhz RAM.
Expected behavior
I expect .Touched() to fire only when a physical touch should have been possible.