Rotating a Part on all Axes?

I’m trying to rotate a part on all axes, but it turns out to be super slow and choppy. I’m trying to achieve the dice-roll from Mario Party.

This is the code I currently have:

repeat 
    wait(0.05) 
	Timer = Timer + 0.05 
 	local X = Die.Orientation.X + 1
 	local Y = Die.Orientation.Y + 1
 	local Z = Die.Orientation.Z + 1
 	Die.Orientation = Vector3.new(X, Y, Z)
until Timer == 50

How can I achieve this in a more clean, and smooth way?
(The die is just a part with decals)

1 Like

You should use TweenService as so:

local TS = game:GetService("TweenService")
local TI = TweenInfo.new(1)

local Tween = TS:Create(Die, TI, {Orientation = Die.Orientation + Vector3.new(180, 180, 180)}) -- Creates the animation, set to 360 if you want it to turn around all the way
Tween:Play() -- Plays the animation
Tween.Completed:Wait() -- Waits until the animation is done
1 Like

This doesn’t seem to produce the full rotation I was hoping for.

Edit: Didn’t see your comment that says to replace with 360 for a full rotation!

1 Like

I’m not too sure how to describe this-- but it isn’t a full-speed kind of rotation. It almost slows down when it is about to reach its destination before looping again. Is there a way to keep a steady rotation flow?

Edit: Here’s my code:

local Die = game.Workspace.Union
local TS = game:GetService("TweenService")
local TI = TweenInfo.new(0.8, Enum.EasingStyle.Linear, Enum.EasingDirection.Out, -1)
local Tween = TS:Create(Die, TI, {Orientation = Die.Orientation + Vector3.new(360, 360, 360)}) -- Creates the animation, set to 360 if you want it to turn around all the way
Tween:Play() -- Plays the animation

wait(4)

Tween:Cancel()

You can see in this video that it slows-down around five and it is displayed for much longer.

What if you took a more “linear” approach? An idea I have might be to add randomization, and “steps.”

Basically, each “step”, tween it by a full 90 degrees in a given direction (left, right, up, down) and make it do this super quickly.

I’m not sure how good this would turn out, but it’d definitely cover every side of the dice; especially if you run each step’s tween fast enough.

I tried this approach but it didn’t seem to be smooth because of the sudden change of direction.

Perhaps I’m doing it wrong?

Try 3 different tweens for each of Orientation.X, .Y, and .Z

Making them out of phase might make it interesting. But i’m not sure what would happen. Give it a try and see what happens

1 Like

Are you sure that the dice rolled in the video you posted is also a full-axis rotation? It might be that they’re just rotating 2 axes.

2 Likes

I agree, it likes like two axis rotation that’s 180 degrees out of phase. When they overlap a transition occurs, and when one dominates it spins one way.

image

1 Like

Yeah, taking a second look it does look like this. How can I recreate this?

1 Like

Hmm, I’m thinking using CFrameFromAxisAngle but it might get tricky using TweenService since it only applies one Tween/property.

The other way is to manually calculate what the proportions each axis is in each standard X,Y,Z orientation, and then tween those accordingly with three tweens like I mentioned earlier.

The third way, which is what I would try before calculating, is to mess around with the numbers and play around with it if you’re not time constrained. You might end up getting something that you like, and you might also end up getting a feel for what the numbers do when you change them.

How do you mean, in regards to the second way.

In the video it looks like it’s rotating the 2 axes, but at the same time? How can I tween the same object on different axes simultaneously?

I am fairly certain that this is rotating on all three axes. The problem is that at some point, two of the axes line up. This creates gimbal lock, which creates the problem you see. There are a couple of ways around this, one of them would be to change the speeds at which the various axes rotate, creating an imperfect yet easy solution which should be adequate for your use-case.
You can also tween the CFrame using quaternion vectors, but I couldn’t even get you started there.

1 Like

I don’t think using three axes allows for certain sides of the die to be in view of the camera. You can kinda see it in the post earlier where the number 1 is never really in view.

Haven’t exactly tested this out with two axes but I’ll let you know when I do.

Edit: it could also be the timing as someone mentioned earlier. I’ll play around with the amount of axes I’m moving.

I’ve played around with some stuff, however, I still cannot recreate the smooth spinning of dice like the one in the video I posted.

The goal is to have every side of the dice, somehow make an appearance to be in view, so rotating on all axes is what I am trying to accomplish. (sorry for sloppy code, just trying to make it work)

local TweenService = game:GetService('TweenService')
local DiceModel = workspace.Union
local TweenInfo = TweenInfo.new(0.8, Enum.EasingStyle.Linear, Enum.EasingDirection.Out)
local Times = 0
local Goal = {}

local function ChangeDirection(Dir)
	if(Dir == 1) then
		Goal.Orientation = DiceModel.Orientation + Vector3.new(180, 360, 180)
	elseif(Dir == 2) then
		Goal.Orientation = DiceModel.Orientation + Vector3.new(360, 180, 180)
	elseif(Dir == 3) then
		Goal.Orientation = DiceModel.Orientation + Vector3.new(180, 180, 360)
	end
end
repeat 
	Goal = {}
	ChangeDirection(math.random(1, 2))
	local Tween = TweenService:Create(DiceModel, TweenInfo, Goal) -- Creates the animation, set to 360 if you want it to turn around all the way
	Tween:Play()
	Tween.Completed:Wait()
	Times = Times + 1
until Times == 15

The issue with this is that the direction change is very abrupt. Someone mentioned earlier in the post that it may have to do with the timing, but adjusting so you rotate more on one axes seems to have caused certain sides of the die to never make an appearance.

Another issue is that there is a brief moment where when I transition to a new Tween, it pauses. It is very tiny but will be noticeable in my game and an issue. The goal is to give every side of the die a chance to appear an equal amount.

Any help would be appreciated!

From my experience and calculations, @JarodOfOrbiter, the axes will never compete with each other. The only reason some faces get shown more is because there are constants. Every axis is rotating at a constant and congruent speed, which basically means that you are going to see the same things repeating over and over again. Notice how it shows 5 a lot, but if you were to change the decals around, another number will be shown more.


I would recommend to use:

math.random(-360, 360)

for each axis as that allows each axis to move in both directions at 360 degrees(clockwise and counter-clockwise). You are also going to need some extra code to adjust the time it takes to finish the tween because if each axis only turns by 1 degree it’s going to look unnatural.

1 Like

Does this approach combat the sudden-changing of direction?

I tried doing this but it still ends up suddenly shifting direction.

I like to use RunService for stuff like this, since it allows for smooth movements.

local RunService = game:GetService("RunService")

local ROTATION_DEGREES = 180
local die = workspace.Union

while true do
	local delta = RunService.Stepped:Wait()

	local rotation = math.rad(ROTATION_DEGREES * delta)
	die.CFrame = die.CFrame * CFrame.Angles(
		rotation,
		rotation,
		rotation
	)
end

Alternatively, you can tween this:

local rotations = {
	CFrame.Angles(
		math.rad(360),
		math.rad(360),
		math.rad(360)
	),
	CFrame.Angles(
		math.rad(-360),
		math.rad(-360),
		math.rad(-360)
	)
}

local tweenInfo = TweenInfo.new(0.8, Enum.EasingStyle.Linear)

for i = 1, 15 do
	local rotation = rotations[Random.new():NextInteger(1, #rotations)]
	local tween = TweenService:Create(die, tweenInfo, { CFrame = die.CFrame * rotation })
	tween:Play()
	tween.Completed:Wait()
end

Thanks for all the help, everyone!

As it stands, TweenService directly on the part’s orientation was not the best way to accomplish this. However, @VegetationBush suggested I use BodyAngularVelocity to rotate it completely.

I applied TweenService to the AngularVelocity by applying a stronger force on each axes. This is the best way to accomplish the rotation done in the video.

Once again, thank you @VegetationBush and everyone else who tried to help.

1 Like