How to determine when two objects are intersecting (but touching is okay)

So, what I have made is a wall placement system and I tried to add a feature where if the wall was directly intersected with another wall, it would destroy itself.


The code to check all this was

for _, otherWalls in pairs(workspace.Walls:GetChildren()) do
if otherWalls:IsA(“Model”) then
if (wall.PrimaryPart.Position - otherWalls.PrimaryPart.Position).magnitude < 0.0001 then

However, the issue surfaced rather quickly. It would only consider objects to be intersected at some angles and points.

An alternative to explore are rays, where I might be able to use an algorithm to find out if two lines are intersecting. But I am unsure whether that will prevent me from connecting a wall to another (see example to the right of the provided image)

GetTouching would never align with the purpose of the task that the code has, because of the issue previously mentioned(…“But I am unsure whether that will prevent me from connecting a wall to another (see example to the right of the provided image)”), however this time it is definitely going to prevent me from connecting walls.

As always, any help provided whether big or small is always appreciated.

4 Likes

As far as I remember, :GetTouchingParts will only return intersecting parts, so you could try that.

I also made a script a long time ago which consistently replaces .Touched. It will work for your case after modifications.

1 Like

GetTouching wouldn’t help due to that I can’t determine ‘how’ intersected the part is. But cool script regarding the touchEnded thing :+1:

Actually, it would. You could use it to filter out everything that doesn’t intersect and run checks on everything else.

I am sorry, I don’t follow. The task of the script that has to be fulfilled is that when a wall is completely ‘through’ another wall. It turns red, but if it is merely touching(and by touching, I mean the wall can be inside another part but just not go through the wall), it shouldn’t any effect. How does filtering out everything else that isn’t intersecting contribute to the goal of the task?

I expect that your wall placement system will have more than 2 walls. You can filter out all of the walls that aren’t intersecting using :GetTouchingParts and then run a check for each. You can also make it much easier if they can’t rotate at an angle other than 90° by changing their size instead of actually rotating them. All you have to do now is check the farthest 2 corners of each.

Technically they will always be intersecting due to that they are snapping to a grid. I guess the most viable way to do something like this would check how intersected it is…?

I am not sure if I need to do a hacky method to accomplish this but I know it is possible.

You can cast rays and use a little bit of region 3.

https://developer.roblox.com/en-us/api-reference/datatype/Region3
https://developer.roblox.com/en-us/api-reference/function/WorldRoot/FindPartsInRegion3

2 Likes

How do you suggest I use this in this task though? What do I calculate/quantify? How does this approach solve my issue?

Use a ray? Region 3 detects if parts are intersecting perfectly, like if my characters HumanoidRootPart is inside a specific area, it will return true.

Rays will detect if surfaces are touching by doing

Ray.new(Part.CFrame.p, Part.CFrame.LookVector * 1

1 is the distance, but I suggest you change 1 to something lower.

This doesn’t solve the issue>because of:

Technically they will always be intersecting due to that they are snapping to a grid. I guess the most viable way to do something like this would check how intersected it is…?
I am not sure if I need to do a hacky method to accomplish this but I know it is possible.

What if you used transparent parts for collision and detecting intersections?

Since they aren’t visible by default, you can resize instead of rotating them. Like if the wall is 5x5x1, the rotated variant’s size would be 1x5x5. That way you can avoid complex and inefficient workarounds and your walls will have less complexity when it comes to physics, decreasing potential bugs such as characters being able to climb them when they shouldn’t.

I don’t know whether it works or this is the biggest waste of time I ever did since I’m kinda in a hurry, so might as well not work at all. Basically this script creates a “Wall” class which handles positions, rotations and collisions. You can create a new wall with classWall.new(CollisionSize,WallModelToClone).

local classWall do
	local v3Id = Vector3.new()

	local listWallCollision = 	{}
	local listWallModels = 		{}

	local wallIsColliding = function(self)
		local partColl0 = self.CollisionPart
		local pos0,size0 = partColl0.Position, partColl0.Size/2
		local x00,x01 = pos0.X-size0.X,pos0.X+size0.X
		local y00,y01 = pos0.Y-size0.Y,pos0.Y+size0.Y
		local z00,z01 = pos0.Z-size0.Z,pos0.Z+size0.Z
		for _, partColl1 in next, listWallCollision do
			local pos1,size1 = partColl1.Position, partColl1.Size/2
			local x10,x11 = pos1.X-size1.X,pos1.X+size1.X
			local y10,y11 = pos1.Y-size1.Y,pos1.Y+size1.Y
			local z10,z11 = pos1.Z-size1.Z,pos1.Z+size1.Z
			
			if (x10<x00 and x00>x11) or (x10>x00 and x00<x11) then
				if (x10<x00 and x00>x11) or (x10>x00 and x00<x11) then
					if (x10<x00 and x00>x11) or (x10>x00 and x00<x11) then
						return true
					end
				end
			end
		end
	end

	local wallCheckValidity = function(self)
		if self:IsColliding() then
			self:Destroy()
			return false
		end
	end

	local wallTilt = function(self,direction)
		direction = direction or 1
		local partColl = self.CollisionPart
		local cf = partColl.CFrame
		partColl.Size = Vector3.new(partColl.Size.Z,partColl.Size.Y,partColl.Size.X)
		partColl.CFrame = cf

		if self:CheckValidity() then
			local modelVisual = self.VisualModel
			modelVisual.CFrame = modelVisual.CFrame*CFrame.Angles(0,math.rad(90)*direction,0)
		end
	end

	local wallSetPosition = function(self,position)
		local partColl = self.CollisionPart
		partColl.CFrame = CFrame.new(position)

		if self:CheckValidity() then
			local modelVisual = self.VisualModel
			modelVisual.CFrame = modelVisual.CFrame-modelVisual.CFrame.Position+position
		end
	end

	local wallDestroy = function(self)
		local partColl = self.CollisionPart
		local modelVisual = self.VisualModel
		listWallCollision[modelVisual] = nil
		table.remove(listWallModels,table.find(listWallModels,modelVisual))
		partColl:Destroy()
		modelVisual:Destroy()
	end

	classWall = {
		new = function(size,model)

			local modelVisual = model:Clone()
			modelVisual.Parent = workspace

			local partColl = Instance.new("Part")
			partColl.Anchored = true
			partColl.Transparency = 1
			partColl.Parent = workspace

			listWallCollision[modelVisual] = partColl
			listWallModels[#listWallModels+1] = modelVisual

			return {
				Position = v3Id,
				Size = size,
				VisualModel = modelVisual,
				CollisionPart = partColl,

				IsColliding = wallIsColliding,
				CheckValidity = wallCheckValidity,
				SetPosition = wallSetPosition,
				Tilt = wallTilt,
				Destroy = wallDestroy
			}
		end
	}
end

do
	local wall1 = classWall.new(Vector3.new(8,4,1),somemodel1)
	local wall2 = classWall.new(Vector3.new(5,5,1),somemodel2)

	wall1:SetPosition(Vector3.new(0,0,0))
	wall2:SetPosition(Vector3.new(5,0,0))
end
3 Likes

Hey oh! I’m way late, so my reply is mostly to help others who stumble across this post. The solution is actually quite simple. The method BasePart:GetTouchingParts() can be used to return a table of all intersecting parts. What is good about this method is that it does all the work for you, because it doesn’t include parts that aren’t intersecting (inside the other part). So if you have a part that is up against the wall but not inside it it will not be deleted. Here’s a simple method to delete all intersecting parts:

function DeleteIntersectingParts(Part)
    -- Retrieves a table of all intersecting parts
    local IntersectingParts = Part:GetTouchingParts();

    -- Loops through the table
    for iterator,intersectingPart in ipairs(IntersectingParts) do
        -- Destroys each part in the table
        intersectingPart:Destroy();
    end;
end;
2 Likes