How can I create a UI Spinning Wheel?

Here is what I want to make:


I want to make a UI Spinning Wheel like the one above, that works and has custom chances of spinning each prize. I don’t know how to make this because I don’t know anything about AbsolutePosition or any type of that stuff. I don’t even know if that is to be involved. I tried to ask here because I found no tutorial on the DevForum or YouTube. I do NOT want to use a free model. I want someone to walk me through a script. Thanks!

If you want to try the wheel above out for yourself, go to 1% Win Obby - Roblox.

14 Likes

Here’s the thought process. You’re going to be using UI rotation, and so you’ll likely need to use TweenService to do it. You’ll have to determine the prize based on the final rotation, so you can either randomly spin it with the tween, and determine the prize, or determine the prize, and then play the tween. Either works. Then you can give the player the tool based on the rotation.

Now an issue is you’ll probably have to directly find the rotational values yourself, but that’s life. :\

3 Likes

These actually aren’t terribly hard to make, so you’ll be using the Rotation property on the UI Instance, and resetting the rotation back to 0 each time you call your spin function.

Step 1: Create a wheel rewards module

-- This is an array of rewards
local rewardsModule = {
    rewardOne, -- Index 1
    rewardTwo, -- Index 2
    rewardThree, -- Index 3
    rewardFour, -- Index 4
    rewardFive, -- Index 5
    rewardSix, -- Index 6
    rewardSeven, -- Index 7
    rewardEight -- Index 8
}

return rewardsModule

Step 2: Finding the angles:
A full circle is 360°

You have 8 prizes on the wheel so you need to divide the circle by 8
360/8 = 45° per reward

local REWARD_DEGREE = 45

Step 3: Get angle of reward number

local randomRewardIndex = rewardsModule[math.random(1, #rewardsModule)] 
local targetRotationAngle = (randomRewardIndex - 1) * REWARD_DEGREE -- the angle on the wheel the prize will be at

The reason behind subtracting randomRewardIndex by 1 is because our start rotation on the wheel is 0 for position 1. Therefore you need to subtract the randomRewardIndex by 1 to get the correct angle, as shown on the wheel picture example above.

Step 4: Tween the rotation of UI Instance to our targetRotationAngle

local fullSpins = 4 -- how many times during the tween we want the wheel to spin before landing on our prize
local endRotation = (360 * fullSpins) * targetRotationAngle

local tween = TweenService:Create(instance, tweenInfo, {
    Rotation = endRotation
})

instance.Rotation = 0 -- reset this or else over time the angle won't be accurate.
tween:Play() -- play the rotation animation!
10 Likes

Thank you! I will try this out.

3 Likes

Curious, is there a way to set custom chances for each reward index?

3 Likes

Yeah you can do a weighted table I’d browse the devforum or online to see if someone released a weighted table. But basically you’d use the same module layout for the rewards, but each item would have a “weight” which would be the chance of getting the item.

When doing a weighted table just make sure all of the chances add up to a total of 100!

Your rewards would look like this:

local rewards = {
    {itemName = "item", chance = 30},
    {itemName = "item", chance = 30},
    {itemName = "item", chance = 30},
    {itemName = "item", chance = 30},
    {itemName = "item", chance = 30},
    {itemName = "item", chance = 30},
    {itemName = "item", chance = 30},
    {itemName = "item", chance = 30},
}

Then you’d do something like this after you have the random generator code

local randomItemIndex, randomItemData = generateRandomItem(table.clone(rewards))

spinWheel(randomItemIndex)

This tutorial might be helpful for the weighted chance system

Just modify your return statement in the weighted function to return the index and item data

9 Likes

Thanks! Might take a while to actually test the whole system because I realized I didn’t even have a spinning wheel ui that has 8 equal parts lmao

3 Likes

Okay so, I might be doing something wrong, but this isn’t working as expected for me. Here are the two scripts I have made:

module script

local rewards = {
	["1"] = 999,
	["2"] = 1,999,
	["3"] = 2,999,
	["4"] = 3,999,
	["5"] = 4,999,
	["6"] = 5,999,
	["7"] = 6,999,
	["8"] = 7,999,
}

return rewards

client script

local REWARD_DEGREE = 45
local wheel = script.Parent.Img
local spin = wheel.Spin
local rewardsModule = require(game:GetService("ReplicatedStorage").SpinnerRewards)
local fullSpins = 4
local TweenService = game:GetService("TweenService")

spin.MouseButton1Down:Connect(function()
	local randomRewardIndex = rewardsModule[math.random(1, #rewardsModule)] 
	local targetRotationAngle = (randomRewardIndex - 1) * REWARD_DEGREE
	local endRotation = (360 * fullSpins) * targetRotationAngle
	local tween = TweenService:Create(wheel, TweenInfo.new(3, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {Rotation = endRotation})
	wheel.Rotation = 0
	tween:Play()
	print(randomRewardIndex)
end)

can’t really talk much longer sorry if its not much thanks again!

4 Likes

Hey, I figured out most of the problems. I got the wheel to spin a random number (it always landed on 1), and more. I have one problem though. The prize isn’t what is spun on the wheel. I made a table of what the outputs are in relation to what is spun on the wheel:

2 to 8
8 to 2
4 to 6
6 to 4
3 to 7
7 to 3
5 Spins Correctly
1 Spins Correctly

Here is the modified version of the script I made since yours didn’t quite work as expected:

local REWARD_DEGREE = 45
local wheel = script.Parent.Img
local spin = wheel.Spin
local rewardsModule = require(game:GetService("ReplicatedStorage").SpinnerRewards)
local fullSpins = 4
local TweenService = game:GetService("TweenService")

spin.MouseButton1Down:Connect(function()
	local randomRewardIndex = rewardsModule[math.random(1, #rewardsModule)] 
	local targetRotationAngle = (randomRewardIndex-1) * REWARD_DEGREE
	local endRotation = (360 * fullSpins) + targetRotationAngle
	local tween = TweenService:Create(wheel, TweenInfo.new(3, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {Rotation = endRotation})
	wheel.Rotation = 0
	tween:Play()
	print(rewardsModule[randomRewardIndex])
end)

Here is the rewards table as well:

local rewards = {
	1,
	2,
	3,
	4,
	5,
	6,
	7,
	8
}

return rewards

I can’t have the rewards as anything else but numbers 1-8, but I know a way around that
Heres a video of the wheel itself while testing it:

I hope this helps. Thank you again for the help you’ve given me so far! :slight_smile:

5 Likes

I think somewhere we might have messed up the formula for calculating the rotation. Disregard the targetRotationAngle variable we had made. The formula below should definitely work. Also before playing the tween make sure to set the rotation of the frame to 0

local fullSpins = 4
local randomRewardIndex = rewardsModule[math.random(1, #rewardsModule)] 

local endRotation = -((360 * -fullSpins) + (REWARD_DEGREE) * (randomRewardIndex - 1)))
10 Likes

tysm

you should make a community tutorial with this tbh

also you need to remove the last parethesis on that last line there was an extra one

if you do make a community tutorial mention me

5 Likes

No problem! I’ll definitely end up making a community tutorial for sure!

5 Likes

Hey! How would you add a cooldown to the wheel so it cannot be spam clicked?

2 Likes

You’d create a boolean to track if it’s currently on cooldown.

For example:

local cooldown = false

local function spinWheel()
    if cooldown then
        -- code below wont run because cooldown is set to true
        return
    end

    cooldown = true

    -- do spinning stuff here

   -- delay x amount of seconds to set cooldown back to false
   task.delay(2, function()
       cooldown = false
   end)
end
3 Likes

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