Play sound on spinning wheel

I would like to play a click sound as my wheel spins. It should play when every time a new “slice” of the wheel passes the arrow at the top.

My code for spinning the wheel is as follows:

function SpinWheel(endSliceNumber: number)
    local fullSpins = 5
    local sliceStartRot, sliceEndRot = 
    SpinWheelData.wheelRotations[endSliceNumber].startRot, SpinWheelData.wheelRotations[endSliceNumber].endRot
    local randomNumberBetweenRotations = math.random(sliceStartRot, sliceEndRot)
	
    local endRotation = (360*fullSpins) + randomNumberBetweenRotations
	
    local tween = TweenService:Create(
	    spinsUI.Wheel, 
	    TweenInfo.new(3, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), 
	    { Rotation = endRotation }
    )
    spinsUI.Wheel.Rotation = 0
    tween:Play()
    tween.Completed:Wait()
end

This code works as expected and basically spins the wheel 5 times before ending up at the desired end slice (the randomNumberBetweenRotations is just to add some random offset but still ensure the arrow lands in the correct slice).

There are 6 slices on my wheel and I would like to play a sound every time a new one passes the arrow. Not sure how to achieve this so any pointers in the right direction would be appreciated.

Thanks in advance :slightly_smiling_face:

4 Likes

For those interested in a solution I’ve found, here’s what I did:

  • Assuming you know the exact start and end rotations for each slice (like I did), you can populate a table with their values. This only has to be done once (for me, when the script starts). Since my SpinWheel function also spins a certain number of full spins too, I added the equivalent rotations for those spins too…
local rotationEquivalents: { number } = {}

for _,v in SpinWheelData.wheelRotations do
	for i = 1, fullSpins+3 do
		table.insert(rotationEquivalents, v.startRot*i)
		table.insert(rotationEquivalents, v.endRot*i)
	end
end
  • As the tween is playing, we can bind a function to RunService.RenderStepped that calculates the closest rotation to the slice we’re currently on. If the slice we’re on is the same slice as before, we don’t play a sound. However, if it’s a new one, we can play our sound.
-- basic function to get the closest number to the current wheel rotation
local function getClosestRotationToWheel(): number
    local wheelRot = spinsUI.Wheel.Rotation
	local closestNum = math.huge
	
	for _,v in rotationEquivalents do
		if math.abs(wheelRot-v) < math.abs(wheelRot-closestNum) then
			closestNum = v
		end
	end
	
	return closestNum
end

-- this function can be bound
local lastPlayedRotation = 0
RunService:BindToRenderStep("SpinSound", 100, function()
    local closestRotation = getClosestRotationToWheel()	

	if lastPlayedSoundRotation ~= closestRotation then
		lastPlayedSoundRotation = closestRotation		
		SoundService.wheel_click:Play()
	end
end)
  • When the tween ends or your GUI is closed, just make sure to unbind the function from RenderStepped to prevent unnecessary performance issues.
RunService:UnbindFromRenderStep("SpinSound")

You’d of course have to write your own logic to bring this all together in your script or module, but these are the key parts of the system. Copying and pasting the code will not immediately make it work, you’ll have to structure the code properly and define the same variables that I have defined.

NOTE: This is simply my own solution and it may not be the most performant or efficient one as I have not tested it compared to other solutions. It is also not perfect and can probably be improved but I’m leaving this here so you can perhaps use and improve it in your own project.

3 Likes

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