Help with Click Detection on Circular UI Stroke (Osu-style Event)

I want to create an Osu-style circular UI event where a shrinking circle (Click frame) must be clicked exactly on the stroke of a larger circle (Area frame with UIStroke) to succeed. The click must happen strictly on the stroke of the Area frame, and it should not count as success if the click is either inside the center or outside the stroke. I have tried various tests but have not been able to achieve a functional result yet.

Example image: the green represents the area, and the black represents the shrinking area.

3 Likes

I found a way to do it, I’m not sure if it’s the best, but for anyone who wants to know, here it is:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")
local Players = game:GetService("Players")

--------------------
--|    Library   |--
--------------------
local _L = require(ReplicatedStorage:WaitForChild("Core"):WaitForChild("Library"))

-------------------
--|    Variables   |--
-------------------
local Player = Players.LocalPlayer
local PlayerGui = Player:WaitForChild("PlayerGui")
local CatchGui = PlayerGui:WaitForChild("Gui"):WaitForChild("Catch")
local Tool = script.Parent

local Area = CatchGui:WaitForChild("Area")
local Click = CatchGui:WaitForChild("Click")

local strokeThickness = Area.UIStroke.Thickness
local areaSize = Area.Size.X.Scale * 400 --Size of frame: 400x400

local function calculateAreas()
	local inRadius = areaSize / 2
	local inArea = math.pi * inRadius^2 -- Internal area

	local outRadius = (areaSize + 2 * strokeThickness) / 2
	local outArea = math.pi * outRadius^2 -- External area with border

	return inArea, outArea
end


Tool.Activated:Connect(function()
	local ts = TweenService:Create(Click, TweenInfo.new(10, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut), { Size = UDim2.new(0, 0, 0, 0) })
	ts:Play()

	local inArea, outArea = calculateAreas()

	while true do
		local clickRadius = (Click.Size.X.Scale * 400) / 2
		local clickArea = math.pi * clickRadius^2

		local adjustedInArea = inArea - math.pi * (strokeThickness^2)

		if (clickArea <= outArea) and (clickArea >= adjustedInArea) then
			print("Inside")
		else
			print("Outside")
		end

		wait()
	end
end)

If anyone has a better alternative, feel free to leave it here so we can know.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.