I need a little help with an emote system; mainly the emote selection.
Like I need to get the degrees of the cursor relative from the center point;
I’m not good at math… so any help would be appreciated.
I need a little help with an emote system; mainly the emote selection.
Like I need to get the degrees of the cursor relative from the center point;
I’m not good at math… so any help would be appreciated.
atan2. You basically just tell it how horizontally and vertically far the mouse is from the center, and it spits out the angle
The only catch is that it gives you the answer in a measurement called radians, so you have to do a quick conversion to get the degrees
So what’s happening here is pretty simple. You first establish the center of your emote wheel, which is usually the middle of the screen. Then you find the distance from that center point to your mouse’s current x and y position
The math.atan2(y, x) takes those distances and calculates the angle. Most atan2 functions are a little weird and want the y value first
Thanks. I’ll try that out and let you know if it works.
Ah, that small offset
The problem is that for your angle to be a perfect 0 or 180 degrees, the vertical distance from your mouse to the center has to be exactly zero. That tiny offset you’re seeing happens because it’s not. I’d say, probably because of the UI top bar - your script is probably calculating the center of the entire window, but the mouse reports its position starting from below that top bar, so the two are never perfectly aligned.
The fix is pretty simple: you need to tell your script to get the center of the actual game viewport, not the whole window.
Grab the camera and use its ViewportSize.
I tried that; but it seems to still have that weird offset.
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local Camera = workspace.CurrentCamera
local UI = script.Parent
local Wheel = UI:WaitForChild("Wheel")
local Rotations = {
[-120] = Wheel.Emote1,
[-60] = Wheel.Emote2,
[0] = Wheel.Emote3,
[60] = Wheel.Emote4,
[120] = Wheel.Emote5,
[180] = Wheel.Emote6,
}
local function getAngle()
local center = Camera.ViewportSize / 2
local cursor = UserInputService:GetMouseLocation()
local dx = cursor.X - center.X
local dy = cursor.Y - center.Y
return math.deg(math.atan2(dy, dx))
end
local function getClosestEmote(angle)
local closestKey = nil
local smallestDiff = math.huge
for key, emote in pairs(Rotations) do
local diff = math.abs(angle - key)
if diff < smallestDiff then
smallestDiff = diff
closestKey = key
end
end
return Rotations[closestKey]
end
RunService.RenderStepped:Connect(function()
local degrees = getAngle()
local selectedEmote = getClosestEmote(degrees)
for _, emote in pairs(Rotations) do
emote.ImageTransparency = (emote == selectedEmote) and 0.4 or 0.7
end
end)
I also tried enabling the IgnoreGuiInset property… but that also doesn’t seem to quite work.
The offset is happening because Camera.ViewportSize and UserInputService:GetMouseLocation() use two different coordinate systems.
So, your center.Y is correct for the viewport, but your cursor.Y is offset by 36 pixels. That’s where the imprecision comes from. The IgnoreGuiInset property only affects how the GUI itself is positioned, it doesn’t change the coordinates returned by this function.
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local mouse = player:GetMouse()
local Camera = workspace.CurrentCamera
local UI = script.Parent
local Wheel = UI:WaitForChild("Wheel")
local Rotations = {
[-120] = Wheel.Emote1,
[-60] = Wheel.Emote2,
[0] = Wheel.Emote3,
[60] = Wheel.Emote4,
[120] = Wheel.Emote5,
[180] = Wheel.Emote6,
}
local function getAngle()
local center = Camera.ViewportSize / 2
local cursor = Vector2.new(mouse.X, mouse.Y)
local dx = cursor.X - center.X
local dy = cursor.Y - center.Y
return math.deg(math.atan2(dy, dx))
end
local function getClosestEmote(angle)
local closestKey = nil
local smallestDiff = math.huge
for key, emote in pairs(Rotations) do
local diff = math.abs(angle - key)
if diff > 180 then
diff = 360 - diff
end
if diff < smallestDiff then
smallestDiff = diff
closestKey = key
end
end
return Rotations[closestKey]
end
RunService.RenderStepped:Connect(function()
local degrees = getAngle()
local selectedEmote = getClosestEmote(degrees)
for _, emote in pairs(Rotations) do
emote.ImageTransparency = (emote == selectedEmote) and 0.4 or 0.7
end
end)
Apparently my emote wheel selection logic was bugged; which is why it looked as if the rotation was being returned wrong. Thanks for the solution!
This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.