How would I determine if a UI is overlapping another UI?

I’m working on a game kinda like JSAB (Just Shapes and Beats) and need to make the player get hurt when he / she touches anything evil, the stuff that is a different color (In this it’s pink).

How would I go about getting the overlap?

3 Likes

You could get the Size of each UI element and compare distances between them along the X and Y axis.

Let’s say that we want to detect an overlap of two UI elements on the X axis. If the difference in absolute X position between the two elements is less than the sum of their absolute X size, you know they must be overlapping. (We are using AbsolutePosition and AbsoluteSize so we don’t have to worry about Scale / AnchorPoint of the UI). It’s just the same for the Y axis as it is the X axis for calculating this.

For example:

We have two frames, they both have an AbsoluteSize of Vector2.new(10,10)

  • Frame1 has an AbsolutePosition of Vector2.new(0,0)
  • Frame2 has an AbsolutePosition of Vector2.new(10,0)

Although these frames are touching, they are not overlapping, so our function (below) should return false. (If we wanted to include touching as “overlapping” too then we would use the <= operator instead of the < operator.)

function areFramesOverlapping(Frame1,Frame2)
	-- X axis overlap detection
	local F1posX,F2posX = Frame1.AbsolutePosition.X,Frame2.AbsolutePosition.X
	local F1sizeX,F2sizeX = Frame.AbsoluteSize.X,Frame2.AbsoluteSize.X
	
	local Xdistance = math.abs(F1posX-F2posX) -- distance (in px) between frames
	local minXdistance = math.abs(F1sizeX+F2sizeX/2)-- min distance w/o overlap
	
	-- Y axis overlap detection
	local F1posY,F2posY = Frame1.AbsolutePosition.Y,Frame2.AbsolutePosition.Y
	local F1sizeY,F2sizeY = Frame.AbsoluteSize.Y,Frame2.AbsoluteSize.Y
	
	local Ydistance = math.abs(F1posY-F2posY) -- distance (in px) between frames
	local minYdistance = math.abs(F1sizeY+F2sizeY/2)-- min distance w/o overlap

	if Ydistance < minYdistance and Xdistance < minXdistance then return true end -- OVERLAP!!

	return false -- no overlap detected
end

Now, let’s say we have the same frames but different positions:

  • Frame1 has an AbsolutePosition of Vector2.new(0,0)
  • Frame2 has an AbsolutePosition of Vector2.new(9,0)

Woah, now we’re overlapping over the X axis! Putting both of these frames into the function will now return true.

Hope this helps!

Note: I didn’t have time to test this function on my own so please let me know if there are any issues.

29 Likes

Just a quick question… Im not sure if this would work with rotation. Do you think it would.

It would not work with rotation unless rotation is 0 or 180 degrees. If you want something like this to work with rotation that would be extremely complex, roblox still hasn’t been able to reliably make ClipDescendants work with rotated UI elements so I’d imagine the math would be quite difficult to detect this (and is definitely out of my current knowledge).

2 Likes

I could use the rotation like a circle and get the position based on the circumference. That may work, but as you said. Yes, Extremely complex.

I found an alternative way which yielded more accurate results. Only draw back is two of the gui objects doing detection must not be of the same Object.
Meaning you cannot have a ImageLabel detecing another ImageLabel, one must be nested inside a frame in order for this to work.

:x: : Frame will not detect another Frame
:white_check_mark: ImageLabel will detect Frame

local function areFramesOverlapping(myImageLabel)
    local nameOf2ndObject = "exampleFrame"
    if not myImageLabel then -- return if image label doesn't exist
        return
    end

    local guisDetectedAtPosition = playerGUI:GetGuiObjectsAtPosition(myImageLabel.AbsolutePosition.X, myImageLabel.AbsolutePosition.Y)

    for _, v in pairs(guisDetectedAtPosition) do
        if v.Name == nameOf2ndObject then
            return true  -- return true if detected
        end
    end

    return false -- return false if nothing is detected
end
7 Likes