Hi there, I’m currently trying to make a radial menu for my game using an old tutorial from the Dev Wiki, which has been removed and managed to retrieve it using archive.org, here is the link: Creating a Radial Menu (archive.org)
The original tutorial was meant to work with controllers so I had to readapt it to work with PC (and eventually mobile), which is totally possible since it’s mentioned in the article itself. As you can see I made a few changes, such as adding an offset so that the BuildMenu()
function would take into account the AnchorPoint of the buttons of the menu.
The problem is the following: for some reason the checkButton()
function, whose job is to return a button from the menu based on the mouse X,Y position, keeps returning the last button of the menu, regardless of the mouse position, completely ignoring the others. I’m not sure why this is happening, math isn’t my strongest suit. I believe the math is correct, but it’s also true that I edited the formulas in BuildMenu()
so that the AnchorPoint would offset the buttons correctly, so maybe that’s what’s causing the issue?
local Service = require(game:GetService("ReplicatedStorage").Utils.Modules.Services)
-- UI ELEMENTS --
local IconsFolder = script:WaitForChild("Icons")
local Menu = script.Parent:WaitForChild("Menu")
local MenuIcons = Menu:WaitForChild("Icons")
local Current = script.Parent:WaitForChild("Current")
local buttonHolderTemplate = script:WaitForChild("ButtonTemplate")
-- MENU VARIABLES --
local menuOpen = false
local ANGLE_OFFSET = 90
local RADIUS = 0.55
local menuItems = {}
-- FUNCTIONS --
local function BuildMenu(unlockedElements)
for i,element in pairs(unlockedElements) do
local Icon = IconsFolder:FindFirstChild(element):Clone()
local buttonInfo = {}
buttonInfo.Icon = Icon
local offsetX = (0.5 - Icon.AnchorPoint.X) * Icon.Size.X.Offset
local offsetY = (0.5 - Icon.AnchorPoint.Y) * Icon.Size.Y.Offset
local angle = (360 / #unlockedElements) * (i - 1)
local angleRadians = math.rad(ANGLE_OFFSET + angle)
buttonInfo.Position = UDim2.new(
0.5 + RADIUS * math.cos(angleRadians) - offsetX,
0,
0.5 - RADIUS * math.sin(angleRadians) - offsetY,
0)
buttonInfo.Vector = Vector2.new(math.cos(angleRadians), math.sin(angleRadians))
buttonInfo.Range = 360 / #unlockedElements
--menu icon visual
Icon.Transparency = 0
Icon.Parent = MenuIcons
table.insert(menuItems,buttonInfo)
end
end
local function Init()
local elements = {"Water","Fire","Air","Ore","Bloom","Surge"}
BuildMenu(elements)
end
Init()
local con
local function checkButton(mousePos :Vector2)
for i = 1, #menuItems, 1 do
local item = menuItems[i]
local dotProduct = mousePos.X * item.Vector.X + mousePos.Y * item.Vector.Y
local angle = math.acos(dotProduct / mousePos.Magnitude) print(angle, math.rad(item.Range) / 2)
if angle <= math.rad(item.Range) / 2 then
return item.Icon
end
end
return nil
end
Service.CAS:BindAction("openInfusions",function(actionName, inputState, _inputObj)
if inputState == Enum.UserInputState.Begin then
Current:TweenPosition(UDim2.fromScale(0.5,0.5),Enum.EasingDirection.In,Enum.EasingStyle.Linear,0.15,true,function()
Current.Visible = false
for i,button in pairs (menuItems) do
local icon : Frame = button.Icon
icon.Visible = true
icon:TweenPosition(button.Position,Enum.EasingDirection.In,Enum.EasingStyle.Linear,0.1)
end
con = Service.RunS.Heartbeat:Connect(function(dt)
local button = checkButton(Service.UIS:GetMouseLocation())
--print(button)
end)
end)
end
if (inputState == Enum.UserInputState.End or inputState == Enum.UserInputState.Cancel) then
for i,button in pairs (menuItems) do
local icon : Frame = button.Icon
icon:TweenPosition(UDim2.fromScale(0.5,0.5),Enum.EasingDirection.In,Enum.EasingStyle.Linear,0.1,false,function()
icon.Visible = false
end)
end
task.wait(0.1)
Current.Visible = true
Current:TweenPosition(UDim2.fromScale(0.5,0.95),Enum.EasingDirection.In,Enum.EasingStyle.Linear,0.15,true)
end
end,true,Enum.KeyCode.Q)
Thanks in advance for the help!