How can I make two frames collide?

Hello.

Basically I am making a Touhou EoSD recreation just to merely learn more about scripting and enjoy myself (not gonna publish it obviously). I need the player to stay in a frame (game screen) and then the UI besides it, since I don’t want the player moving towards the UI… How would I do that?

Not only that, but I also need to detect when the player (a frame) touches an item / enemy / bullet etc… Long story short: How can I make two GUI objects collide?

try viewpoint frame.
it will get some input(camera of player) and add it on gui so you can add viewpoint frame into playerGUI, script it on player camera and then by script move a screen a bit.

There’s no built-in method so you will need to make it from scratch. Simplest method is circle-circle collision but everything will be treated like a circle. A more complex yet simple method is AABB where everything is a rectangle/square, it’s more complex but better results. If you want perfect collisions you can look into SAT or GJK but you will need to draw each vertex by hand. Note that GJK and SAT are very very complex.

nice thanks. I am curious about square collision since that’s what I need, can you give me more information about it? I am interested to know

To keep the player’s character within the game screen, you can use a combination of the “ViewportSize” property of the camera and the “ClipsDescendants” property of the game screen frame. Here’s an example of how you can implement this:

-- Get the player's character
local character = game.Players.LocalPlayer.Character or game.Players.LocalPlayer.CharacterAdded:Wait()

-- Get the game screen frame and the camera
local gameScreen = script.Parent
local camera = workspace.CurrentCamera

-- Set the ClipsDescendants property of the game screen frame to true
gameScreen.ClipsDescendants = true

-- Connect to the character's "HumanoidRootPart" property changed event
character.HumanoidRootPart:GetPropertyChangedSignal("Position"):Connect(function()
	
	-- Get the size of the game screen frame
	local screenSize = gameScreen.AbsoluteSize
	
	-- Get the viewport size of the camera
	local viewportSize = camera.ViewportSize
	
	-- Calculate the maximum position that the character can have without going outside the game screen frame
	local maxX = (screenSize.X / 2) - (viewportSize.X / 2)
	local maxY = (screenSize.Y / 2) - (viewportSize.Y / 2)
	
	-- Clamp the character's position within the game screen frame
	local clampedPosition = character.HumanoidRootPart.Position:Clamp(Vector3.new(-maxX, -maxY, -9999), Vector3.new(maxX, maxY, 9999))
	character.HumanoidRootPart.CFrame = CFrame.new(clampedPosition)
	
end)

This code gets the game screen frame and the camera, sets the ClipsDescendants property of the game screen frame to true, and connects to the character’s “HumanoidRootPart” property changed event. Whenever the character’s position changes, the code calculates the maximum position that the character can have without going outside the game screen frame, clamps the character’s position within the game screen frame, and sets the character’s CFrame to the clamped position.

As for detecting collisions between GUI objects,

There is no built-in collision detection functionality for GUI objects in Roblox.

However, you can simulate collisions between GUI objects by using their “AbsolutePosition” and “AbsoluteSize” properties. Here’s an example of how you can detect collisions between two GUI frames:

-- Get the two GUI frames that you want to detect collisions between
local frame1 = gameScreen.Frame1
local frame2 = gameScreen.Frame2

-- Connect to the "RenderStepped" event to check for collisions every frame
game:GetService("RunService").RenderStepped:Connect(function()
	
	-- Get the absolute positions and sizes of the two frames
	local frame1Position = frame1.AbsolutePosition
	local frame1Size = frame1.AbsoluteSize
	local frame2Position = frame2.AbsolutePosition
	local frame2Size = frame2.AbsoluteSize
	
	-- Check if the two frames are overlapping
	if frame1Position.X < frame2Position.X + frame2Size.X and
	   frame1Position.X + frame1Size.X > frame2Position.X and
	   frame1Position.Y < frame2Position.Y + frame2Size.Y and
	   frame1Position.Y + frame1Size.Y > frame2Position.Y then
	   
		-- The two frames are colliding
		print("Collision detected!")
		
	end
	
end)

This code gets the two GUI frames that you want to detect collisions between and connects to the “RenderStepped” event to check for collisions every frame. Whenever the two frames are overlapping, the code prints a message to the output indicating that a collision has been detected. You can replace code for detecting collisions between GUI frames:

-- The two frames are colliding, so do something
if frame1.Position == frame2.Position then
    print("Collision detected!")
end

This code checks if the two frames are colliding by comparing their positions, and if they are colliding, it prints a message to the output indicating that a collision has been detected. You can replace the print statement with any code you want to execute when a collision occurs.

To detect collisions between GUI frames and other objects in the game world, you can use the “Touched” event of the frame’s part. Here’s an example of how you can detect when a player touches an item in the game world:

-- Get the player's character and the item
local character = game.Players.LocalPlayer.Character or game.Players.LocalPlayer.CharacterAdded:Wait()
local item = workspace.Item

-- Connect to the "Touched" event of the item's part
item.Part.Touched:Connect(function(hit)
	
	-- Check if the player touched the item
	if hit and hit.Parent == character then
		-- The player touched the item, so do something
		print("Player picked up the item!")
	end
	
end)

This code gets the player’s character and the item, and connects to the “Touched” event of the item’s part. Whenever the player’s character touches the item, the code checks if the player touched the item by comparing the hit object’s parent to the player’s character, and if the player touched the item, it prints a message to the output indicating that the player picked up the item. You can replace the print statement with any code you want to execute when the player picks up the item.

AABB stands for axis-aligned bounding box, a rectangular collision shape aligned to the base axes of the scene, which in 2D aligns to the x and y axis. The code for it is very simple!

local function isColliding(guiObject1: GuiButton, guiObject2: GuiObject)
	local isCollisionOnX = guiObject1.AbsolutePosition.X + guiObject1.AbsoluteSize.X >= guiObject2.AbsolutePosition.X and guiObject2.AbsolutePosition.X + guiObject2.AbsoluteSize.X >= guiObject1.AbsolutePosition.X
	local isCollisionOnY = guiObject1.AbsolutePosition.Y + guiObject1.AbsoluteSize.Y >= guiObject2.AbsolutePosition.Y and guiObject2.AbsolutePosition.Y + guiObject2.AbsoluteSize.Y >= guiObject1.AbsolutePosition.Y
	
	return isCollisionOnX and isCollisionOnY
end

That’s it. Note that this only works if your frames are unrotated.