# Dice - Which face is up?

Discussion in 'Scripting' started by Bones3D, Apr 28, 2008.

1. ### Bones3D

Joined:
Apr 28, 2008
Posts:
314
I'm currently trying to design a board game involving dice with Unity, but I'm a bit confused as to how I can determine which face of each die is up (as well as the location of the adjacent faces relative to it).

While I'm aware I could probably parse the rotational values, I'm concerned Unity's returned values aren't going to be very reliable.

For example, in the editor, I created a cube and changed the orientation by 90 degrees on each axis a few times to determine how the orientation change on each axis would affect the others. Afterwards, I briefly selected a different object and then switched back to the cube. Suddenly, the inspector panel shows the rotational values going from clean, 90 degree increments to a lengthy floating point value like "5.0009641e".

Is there an option besides parsing the orientation values that might work for my needs?

The only other option I can currently think of is to create a set of child collider objects inside each die that would contain a central collider object bound by gravity that would eventually come to rest on the collider face at the bottom of the die. However, I'm worried such a system would quickly bog down Unity when employing more than a couple dice at a time.

Joined:
Oct 10, 2005
Posts:
716
3. ### Bones3D

Joined:
Apr 28, 2008
Posts:
314
Actually, this code fragment posted by freyr in that thread might be enough for what I need and could probably be adapted to identify the adjacent face position/values as well.

Code (csharp):
1. // The 3 low-end expressed in local space vectors.
2. // We don't need the last 3 as their direction
3. // vectors are simply the negative of the
4. // opposite side.
5. // (You will have to change the vectors if
6. //  you have orientated the dice differently.)
7. var sides : Vector3[] =
8.     [Vector3.up,       // 1(+) or 6(-)
9.      Vector3.right,    // 2(+) or 5(-)
10.      Vector3.forward]; // 3(+) or 4(-)
11.
12. function WhichIsUp()  {
13.     var maxY = float.NegativeInfinity;
14.     var result = -1;
15.
16.     for(var i = 0; i < 3; i++) {
17.         // Transform the vector to world-space:
18.         var worldSpace = transform.TransformDirection(sides[i]);
19.         if(worldSpace.y > maxY) {
20.             result = i+1; // index 0 is 1
21.             maxY=worldSpace.y;
22.         }
23.         if (-worldSpace.y > maxY) { // also check opposite side
24.             result = 6-i; // sum of opposite sides = 7
25.             maxY=-worldSpace.y;
26.         }
27.     }
28.     return result;
29. }
My javascript is a bit rusty still, but I think I understand the gist of it though.

4. ### Lka

Joined:
Aug 6, 2006
Posts:
297
You could throw a ray from the top of the dice down to the z axis to see what face it hit.

And with an array you have the value for each face:

dice[0]=1;
dice[1]=1;
dice[2]=3;
...

5. ### Lka

Joined:
Aug 6, 2006
Posts:
297
Even better.. you could know the face value with RaycastHit.textureCoord. This way you don't have to create manually the array and this method should work with n-side dice.

6. ### Bones3D

Joined:
Apr 28, 2008
Posts:
314
Well, it seems that code segment posted by freyr does work, but it's kind of tricky if you didn't specifically design your die model for it ahead of time.

Here's what I eventually came up with:

Code (csharp):
1.
2.     // sets the side definition variables.
3.     // (these have been changed to the literal vector
5.     var sides : Vector3[] =
6.     [Vector3(0, 1, 0),  // 1(+) or 6(-)
7.      Vector3(0, 0, 1),  // 2(+) or 5(-)
8.      Vector3(1, 0, 0)]; // 3(+) or 4(-)
9.
10.
11. function WhichIsUp()  {
12.     var maxY = float.NegativeInfinity;
13.     var result = -1;
14.
15.     for(var i = 0; i < 3; i++) {
16.         // Transform the vector to world-space:
17.         var worldSpace = transform.TransformDirection(sides[i]);
18.         if(worldSpace.y > maxY) {
19.             result = i+1; // index 0 is 1
20.             maxY=worldSpace.y;
21.         }
22.         if (-worldSpace.y > maxY) { // also check opposite side
23.             result = 6-i; // sum of opposite sides = 7
24.             maxY=-worldSpace.y;
25.         }
26.     }
27.     return result;
28. }
29.
30. // display the die value
31. function OnGUI () {
32.    var thisSide = WhichIsUp() + "";
33.    GUILayout.Label (thisSide);
34. }
Combined with this die model (175KB Unity-compatible Cheetah3D .jas file), the above behavior script displays the value of the die's top-most face when the project is run. To test it, simply change the orientation of the die in the editor and run the project again to have it display the result.

For anyone having difficulty getting their own models working right with the above behavior script, here's a couple of suggestions:

First, try adjusting the orientation of your model in your 3D modeling app so that the center of faces one and six are resting on the Y-axis. (When imported into unity, the model should be oriented with side one at the top.)

Next, if you keep getting the wrong result where the number at the bottom of the die is being displayed instead of the top, you may need to swap those sides of the die with each other. The fastest way to do this, is to scale your model by -100% in your 3D modeling app along the axis the faces are centered on. this effectively mirrors your model to the appropriate sides. (Just be sure to flip your object normals immediately after to avoid rendering issues later on.)

Joined:
Mar 25, 2008
Posts:
113