Custom overlapping part checks

Hey again DevForum. I’m having trouble with custom checks for overlapping parts. I’m assuming that I might be doing something wrong in how I’m calculating this but the collisions are all random, I have no idea what could be messing up the system.

In general, the collisions aren’t working when need, and sometimes acting up when not needed.

Here is the code I’m using for calculating overlaps.

local function GenerateItemExtents(Item)
	local CoordinateFrame = Item.PrimaryPart.CFrame
	local Size = Item.PrimaryPart.Size
	return {
		X0 = (CoordinateFrame * CFrame.new(Size.X / 2, 0, Size.Z)), 		-- Top Right
		X1 = (CoordinateFrame * CFrame.new(-Size.X / 2, 0, Size.Z)),	 	-- Top Left
		Z0 = (CoordinateFrame * CFrame.new(Size.X / 2, 0, -Size.Z / 2)),	-- Bottom Right
		Z1 = (CoordinateFrame * CFrame.new(-Size.X, 0, -Size.Z / 2)),		-- Bottom Left
	}
end 

local function CalculatePartOverlap(ItemExtents,IterateExtents) -- Both arguments are the Table returned from above.
	local CollisionX = (((ItemExtents.X0.X > IterateExtents.Z1.X) ==  true) and ((ItemExtents.Z1.X < IterateExtents.X0.X) == true)) or (((ItemExtents.X1.X > IterateExtents.Z0.X) == true) and ((ItemExtents.Z0.X < IterateExtents.X0.X) == true))
    -- Using Y as Z, I don't need the Y values for overlapping.
	local CollisionY = (((ItemExtents.X0.Z > IterateExtents.Z1.Z) ==  true) and ((ItemExtents.Z1.Z < IterateExtents.X0.Z) == true)) or (((ItemExtents.X1.Z > IterateExtents.Z0.Z) == true) and ((ItemExtents.Z0.Z < IterateExtents.X0.Z) == true))
	return(CollisionX == true and CollisionY == true) 
end

I don’t completely understand that code (Never bothered learning about CFrame properties like X0, Z1, etc.), but I thought I’d drop a few resources here in case you didn’t know of them already.

https://www.robloxdev.com/api-reference/function/BasePart/GetTouchingParts
https://www.robloxdev.com/api-reference/function/Workspace/FindPartsInRegion3
https://www.robloxdev.com/api-reference/function/Workspace/FindPartsInRegion3WithWhiteList

EDIT:
Looking at that without just skimming it, I understand it.
I would rather use something like the stuff listed above however, due to the fact that this would only work for rectangular prisms.

Well :GetTouchingParts() would have worked if it didn’t take in parts that are just colliding surfaces. However I might be able to use this function to grab a smaller amount of parts that would actually need overlapping checks instead of calculating collision checks for parts that don’t even need to be checked. Thanks!

Unfortunately this wouldn’t solve my original problem.

I really don’t know if Region3 would fit my boat, I feel like it has too much problems. (From what I hear I don’t have any actual evidence I could pull up.) I might consider this if my math cannot be solved.

1 Like

GetTouchingParts is the recommended way to do this - it takes advantage of information already known to the physics engine to determine contact/overlap.

If you really want to do the calculations yourself, then I can tell you that comparing the world coordinates of the vertices along the world axes is not going to work. Again, I recommend that you use the proper API for it, but if you want to do it yourself, you should look into the Separating Axis Theorem.

1 Like

I would use the proper API, it would have saved me much time, but it can also return parts that aren’t overlapping but just colliding surfaces.

I’m no good with math and stuff but I’ll check if I can get SAT working.

1 Like

You could try using GetTouchingParts with a part that is slightly smaller than the one that you want to test.

I noticed three problems looking over your code. First, it seems like when calculating X0 to Z1 the size is sometimes divided by two, and sometimes not. I’d recommend setting Size to the PrimaryPart’s Size divided by two instead of doing it multiple times later. Second, this is taking the middle cross-section of the parts; any pitch or roll will cause invalid results. A slight note too, Vector3 could be used instead of making new CFrames. Third, unfortunately the overlap tests alone are not sufficient to determine collision. Imagine two squares, one placed with the center of one if its lines nearly touching a corner of the other. In this case, no matter how you imagined it (my definition was ambiguous) the squares will intersect on both the x and y axes.

There are a couple methods to do a convex 2D intersection test. In 2D when objects are intersection, at least one line segment must touch another from the other object. You can perform 4 * 4 (16) line segment to line segment intersection tests. You could also use the fact that when an intersection occurs, a point of one object must be contained in the other. You could for each object convert the other object’s points into local space and easily check the point’s x and z against the part’s x and z size. This would mean that non-intersecting parts would require 4 checks for each point, and 8 point to local space operations. If you use >= and <= instead of < and > then you can detect if a part is touching but not intersecting as well.

A third method would be to calculate the opposite of the Minkowski sum of the points, informally called the Minkowski difference. If the Minkowski difference includes the origin, then the parts intersect (there is a point inside of each of them that when the difference is taken, results in the origin). This is the method described in the joint paper of Gilbert, Johnson, and Keerthi and commonly called GJK. It works in any dimension, may not even need to calculate all the points (16 of them for two quadrilaterals), and works for any convex shape, including those that cannot be described by a closed set of points like a circle or other smooth objects. If you are interested, I have a GJK distance and intersection implementation. I posted an example somewhere on the forum of its use… searching GJK should take you to it, there aren’t many references to GJK on this forum.

Also, I’m not sure what your use case is, but I do have a RBXLua AABB Octree (custom design/implementation). I made this when I was working on a pathfinder back before the Pathfinder service. This Octree allowed me to quickly find out which parts were near each other or within jumping distance below to generate the navigation mesh.

4 Likes