I trying to get something to work in unity 3D. I have modelled a 20 sided dice and 3 want a Cheep, Stable and Reliable mechanic to detect which way up the dice is facing. I think I will detect when the objects velocity reaches zero to call the number (Unless you’d suggest a better way). But I’m honestly not even sure where to start with determining the number. I’m quite new to unity and have only completed 1 2D game.
I code in C# too.
I have many different sided dice to apply this too, so a versatile method would be very desirable.
If you have modeled the dice and imported it I guess you know which directions each side (number) is facing relative to the object space coordinate space. This could be solved in numerous ways. It could be done (as it sounds you like to do):
to find the number based on the orientation of the model
or, to animate the model to face a direction based on a random number draw
However, I assume based on your phrasing, that you want to do 1)
I would recommend setting up a pre-defined number of direction vectors in object space that maps to numbers in a script attached to the dice. This could be done via Inspector or hard-coded in script. For example you could use a Direction associative map for the lookup. What you can do then (as soon as you consider that the dice is no longer rolling), is to calculate which one of the direction vectors that is closest to a reference vector, e.g. world y-axis up. This would also work for non-flat surfaces as long as epsilon is set accordingly to a minimum angle. For example, let’s say this is a script attached to your dice (Psuedo right out of my head into the forum so not checked):
// Setup in Awake() or via inspector....
Dictionary<Vector3, int> lookup = new Dictionary<Vector3, int>();
lookup[Vector3.up] = 1;
lookup[Vector3.right] = 4;
// etc, will of course be a bit more complicated for a non-traditional dice
....
public int getNumber(Vector3 referenceVectorUp = Vector3.up, float epsilonDeg = 5f) {
// here I would assert lookup is not empty, epsilon is positive and larger than smallest possible float etc
// Transform reference up to object space
Vector3 referenceObjectSpace = transform.InverseTransformDirection(referenceVectorUp);
// Find smallest difference to object space direction
float min = float.MaxValue;
Vector3 minKey;
foreach (Vector3 key in lookup.keySet()) {
float a = Vector3.Angle(referenceObjectSpace, key);
if (a <= epsilonDeg && a < min) {
min = a;
minKey = key;
}
}
return (min < epsilonDeg) ? lookup[minKey] : -1; // -1 as error code for not within bounds
}
If you want it to be versatile I would recommend calculating the lookup table based on the mathematics behind the dice layout. Or setup the script direction vectors and epsilon differently based on each dice model.
Hi currently working on this - so it might help somebody else
Add box colliders to each face of your cube, a trigger to your floor and read which collider hits…
if ( Vector3.Dot ( Vector3.up, transform.up ) > 0.9f )
The Dotproduct gives 1 if the transform aligns perfectly upwards and is 0 if the “up” direction of the dice points sideways. “transform.up” corresponds to the green arrow in local coordinates. If the dot product is bigger than 0.9 we can say that the two Vectors point pretty much in the same direction.