Collision detection for GUI's

From Legacy Roblox Wiki
Jump to navigationJump to search

Introduction and what you'll need for experience

Gui's in Roblox don't have standard build-in collision detection like bricks. You may want to create your own collision detection function for making a 2D game with Gui's in Roblox. This tutorial will just teach you the basics, with illustrations and code examples, because you might need to make a whole game engine for a propper functioning game; and that's not what this tutorial is about. You'll need to know a bit of geometry, math, like the terms about square shapes. (vertices, edges, surface, etc.) You'll need to know some things about Gui's, too. Like; the position of a Gui is in its top-left corner.

In this example, shape1 overlaps shape2. With collision detection, it doesn't matter which one overlaps the other first; we're not working with areas! It's about the edges or vertices of the shapes.

The term (or known to you as a concept) collision detection has to do with detecting if edges or vertices of two or more objects are intersecting. With a square/cuboid (it can be [non-]symmetrical), you're checking whether the vertices of the shape intersect with another shape's edges. There are different kinds of collision detection: Ray-box collision, box-box collision, triangle-box collision, circle-box, polygon collision and so on. The one I will explain in this tutorial is box-to-box collision (so with the square or cuboid shape).

Methods

I can think of 3 methods for detecting shapes that intersect, and act with a collision response:

Response method 1

If shape1 is moving downwards for example, and its bottom edge's position is bigger than the top edge's position of shape2 (bottom-top collision), make shape1's position equal to shape2's top edge's position minus shape1's Y size.

shape1.Position=UDim2.new(shape1.Position.X.Scale,0,shape2.Position.Y.Scale-shape1.Size.Y.Scale,0)

Note: the shape will slightly, but not noticeably, overlap the other shape when colliding. That means that the response will act when the shape is already overlapping the other shape; a slight delay (not meant by performance but physical).

Response method 2

If shape1 is moving downwards again, and its bottom edge's position is bigger than the top edge's position of shape2, remove from shape1's Y position:

shape1.Position = shape1.Position + UDim2.new(0,0,(shape1.Position.Y.Scale+shape1.Size.Y.Scale)-shape2.Position.Y.Scale,0)

Note: this is an inefficient method, as it may not be able to handle collision from multiple directions, meaning it will glitch.

Response method 3

If the shapes have collided, set their positions back to their old positions from where before they collided.

There are MANY more methods, and I'll post some links at the end of this tutorial. But remember, this tutorial is ment for box-box collision detection.

What to look out for

There's always one problem though; if the shape is very small or is moving very fast, it often happens that the collision response will be too late and the object will pass right through the other. But don't think of that problem too much. I'm going to use collision response method 1. This whole tutorial will only make sence when using axis-aligned shapes (shapes that aren't rotated or are perpendicular (faced) to the world axis) (ofcoarse you can't rotate Gui's in Roblox (yet), but only to mention so you know that).

What to do

We're about to check whether 2 Gui's are overlapping. You need to go to Roblox studio and go to: Insert>Object>ScreenGui, and put it into the StarterGui. Insert 2 ImageLabel's, Frame's or any other form of Gui's into the ScreenGui, and name them; "Gui1", and "Gui2".I'll give a function that returns true if Gui's have collided, else return false if they haven't. When calling the function, you'll need to give 2 arguments (userdata type): the Gui's. Remember, this is the code example based on my collision response method 1:

function Collide(gui1,gui2)
    local res=false
    if gui1.Position.Y.Scale<gui2.Position.Y.Scale+gui2.Size.Y.Scale and
       gui1.Position.Y.Scale>gui2.Position.Y.Scale-(gui2.Size.Y.Scale/2) and
       gui1.Position.X.Scale<gui2.Position.X.Scale+gui2.Size.X.Scale and
       gui1.Position.X.Scale+gui1.Size.X.Scale>gui2.Position.X.Scale then
        --Downward edge collide
        gui1.Position=UDim2.new(gui1.Position.X.Scale,0,gui2.Position.Y.Scale+gui2.Size.Y.Scale,0)
        res=true
    end
    if gui1.Position.Y.Scale+gui1.Size.Y.Scale>gui2.Position.Y.Scale and
       gui1.Position.Y.Scale+gui1.Size.Y.Scale<gui2.Position.Y.Scale+(gui2.Size.Y.Scale/2) and
       gui1.Position.X.Scale<gui2.Position.X.Scale+gui2.Size.X.Scale and
       gui1.Position.X.Scale+gui1.Size.X.Scale>gui2.Position.X.Scale then
        -- Upward edge collide
        gui1.Position=UDim2.new(gui1.Position.X.Scale,0,gui2.Position.Y.Scale,0)
        res=true
    end
    if gui1.Position.X.Scale+gui1.Size.X.Scale>gui2.Position.X.Scale and
       gui1.Position.X.Scale+gui1.Size.X.Scale<gui2.Position.X.Scale-(gui2.Size.X.Scale/2) and
       gui1.Position.Y.Scale<gui2.Position.Y.Scale+gui2.Size.Y.Scale and
       gui1.Position.Y.Scale+gui1.Size.Y.Scale>gui2.Position.Y.Scale then
        -- Left edge collide
        gui1.Position=UDim2.new(gui2.Position.X.Scale,0,gui1.Position.Y.Scale,0)
        res=true
    end
    if gui1.Position.X.Scale<gui2.Position.X.Scale+gui2.Size.X.Scale and
       gui1.Position.X.Scale>gui2.Position.X.Scale+(gui2.Size.X.Scale/2) and
       gui1.Position.Y.Scale<gui2.Position.Y.Scale+gui2.Size.Y.Scale and
       gui1.Position.Y.Scale+gui1.Size.Y.Scale>gui2.Position.Y.Scale then
        -- Right edge collide
        gui1.Position=UDim2.new(gui2.Position.X.Scale+gui2.Position.X.Scale,0,gui1.Position.Y.Scale,0)
        res=true
    end
    return res;
end

Now if you want to check if the gui's are colliding, you could use the print function to print the result what the function returned in the output window. Example:

print(Collide(game.StarterGui.ScreenGui.Gui1,game.StarterGui.ScreenGui.Gui2))

When the Gui's do collide, it will print true. Else if they don't collide, it will print false. That was my tutorial about collision detection for Gui's, I hope you've learned from it! Thanks for reading!

~Arundel

See Also