I’ve tested two ways of doing it and found both to be reliable. The first is using my GJK distance and intersection module. If you are not familiar with the Gilbert-Johnson-Kerthi algorithm, basically you make a “support” function for each of the primitives to test (the part and the sphere in this case). The support function is called with a direction and should return the point on the primitive furthest in that direction. For a part, it will always be one of its corners. For a sphere, it will be a point on its surface. GJK uses these support functions to look for a plane of separation (whose normal is the direction passed into the support functions).
local GJK = require(script.GJK)
local min = math.min
local up = Vector3.new(0, 1, 0)
local function newPartSupport(part)
local pos = part.Position
local s = part.Size * 0.5
local cf = part.CFrame - pos
local i = cf.RightVector * s.X
local j = cf.UpVector * s.Y
local k = cf.LookVector * s.Z
return function(dir)
return pos
+ (i:Dot(dir) > 0 and i or -i)
+ (j:Dot(dir) > 0 and j or -j)
+ (k:Dot(dir) > 0 and k or -k)
end
end
local function newSphereSupport(sphere)
local pos = sphere.Position
local s = sphere.Size * 0.5
local radius = math.min(s.X, s.Y, s.Z)
return function(dir)
return pos + dir.Unit * radius
end
end
local function isTouching(part, sphere)
return GJK.intersection(
newPartSupport(part),
newSphereSupport(sphere),
up
)
end
local part = workspace.Part
local sphere = workspace.Sphere
while wait() do
print(isTouching(part, sphere))
end
The other method was described by @Flubberlutsch and works well. Here is the script I used to test it. I ran round and hit the ball and made it bounce. Seems reliable:
local part = workspace.Part
local sphere = workspace.Sphere
local isTouching
local function onTouched(other)
if other == sphere then
print 'Touch'
isTouching = true
end
end
local function onTouchEnded(other)
if other == sphere then
print 'Ended'
isTouching = false
end
end
part.Touched:Connect(onTouched)
part.TouchEnded:Connect(onTouchEnded)
while wait() do
print(isTouching)
end
As for a performance comparison, I’d expect the event based one to be more performant. While running both, I noticed a FPS drop on the GJK one from 54.5 to 54.4, which doesn’t seem significant to me. The GJK algorithm calls each support function 6 times while touching and once when not touching and separated on the y axis.