Ideally we would pick the option ahead of time and just use the spinning as a fancy transition. That lets us make sure all spots are fairly likely.
Let's say we have N
equally sized slices on a single circular part
(you could just use a decal for the divisions, or you'd modify this to appropriately weld or otherwise attach extra parts to this one).
1 | local choice = math.random( 0 ,N- 1 ); |
2 | local angle = (choice + 0.5 ) / N * math.pi * 2 ; |
9 | angle = angle + (math.random() - 0.5 ) * math.pi * 2 / N; |
To do the math, we have to pick a deceleration and a number of times to go around. The deceleration should be constant, but we can pick random numbers of times for it to revolve around:
1 | local acceleration = - 1 ; |
2 | local rotations = math.random( 10 , 15 ); |
4 | angle = angle + rotations * math.pi * 2 ; |
Now we just have to solve for what initial speed will take us exactly there.
05 | t: total time (unknown) |
06 | v: initial velocity (unknown) |
08 | x = ((v + a * t) + v) / 2 * t; |
16 | v = -a * sqrt(- 2 * x / a) |
So our initial velocity
is
1 | local initialVelocity = -acceleration * math.sqrt( - 2 * angle / acceleration ); |
Now, we just animate:
01 | local totalTime = initialVelocity / -acceleration; |
02 | local startTime = tick(); |
03 | while startTime + totalTime > tick() do |
04 | local time = tick() - startTime; |
05 | local theta = (initialVelocity + initialVelocity + acceleration * time) / 2 * time; |
06 | part.CFrame = CFrame.Angles( 0 , theta, 0 ) + position; |
10 | part.CFrame = CFrame.Angles( 0 ,angle, 0 ) + position; |
Where part
is the part we are spinning (around the Y axis) and position
is where you want the part to spin.
Note that when the animation stops, we already computed way ahead of time which slot it will land on, choice
(a number 0
to N-1
).
EDIT:
- Fixed name typos with
initialVelocity
- Fixed while condition to use
>
; was <
- Added randomness to initial angle choice