Determining a cube's face up

Hi,

I’m, trying to put together a small proof of concept of a dice game.

As I’m new to Unity i’ve already stumbled upon my first snag. I can’t find a way to determine a cube’s face up, even after googling for about an hour or so.

Here’s the code that throws 5 randomly rotated dice on a bouncy plane (to get a somewhat unpredictable result each time):

    using UnityEngine;
    using System.Collections;
    
    public class Spawn : MonoBehaviour {
    
    	void Start()
    	{
    		
    		for (int x = 0; x <5; x++)
    		{
    				int a = 10;
    				int b = 20;
    				int c = 10;
    				GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
    				cube.AddComponent<Rigidbody>();
    				cube.transform.position = new Vector3((a+x), (b+x), (c+x));
    				cube.transform.rotation = Random.rotation;
    		}
    	}
    }

Is there an easy way for determining the cube’s face up and printing it to console, after they stopped moving?

Many thanks,

R

The six sides of the cube can be identified as:

  • transform.up
  • -transform.up
  • transform.right
  • -transform.right
  • transform.forward
  • -transform.forward

You can test the angle between each one and Vector3.up:

angle = Vector3.Angle(transform.up, Vector3.up);

The one with the lowest angle will be the side facing up. If you are sure the cube will always be flat (i.e. one won’t end up leaning against another), you can stop when you find one below a small threshold.

An alternate calculation is to use Vector3.Dot() between the two vectors. The one closest to 1.0 will be the side facing up.

I finally managed to figure this out, after some fidgeting. I’ll post everything here if anyone else has the same predicament as myself.

  1. For each side of the cube, I’ve created a minuscule object that sits just a fraction of a pixel outside of the cube’s plane (0.045) so it is triggered only when the cube sits flat on a side. Set it to Box Collider On, Trigger Off.
  2. I’ve created two floors: one is the trigger listener and the other needs to be in place for the cube not to fall through the first. (couldn’t find a way to have an object with both box collider and trigger on at the same time… n00b)
  3. I’ve attached the following script to the trigger floor plane:

using UnityEngine;
using System.Collections;

public class Collision : MonoBehaviour {

public string diceval;

void OnTriggerEnter (Collider myTrigger)
{
	if (myTrigger.gameObject.name == "Side1trigger")
	{
		diceval = ("6 is up");
	}
	
	if (myTrigger.gameObject.name == "Side2trigger")
	{
		diceval = ("5 is up");
	}
	
	if (myTrigger.gameObject.name == "Side3trigger")
	{
		diceval = ("4 is up");
	}
	
	if (myTrigger.gameObject.name == "Side4trigger")
	{
		diceval = ("3 is up");
	}
	
	if (myTrigger.gameObject.name == "Side5trigger")
	{
		diceval = ("2 is up");
	}
	
	if (myTrigger.gameObject.name == "Side6trigger")
	{
		diceval = ("1 is up");
	}
}

}

  1. Finally, the script for detecting movement and displaying final dice value, attached to an empty game object in the scene. This also ‘grabs’ the dice I’ve created and drops it with a random rotation to create an unpredictable outcome each time. Floor is bouncy with a factor of 0.6

    using UnityEngine;
    using System.Collections;

    public class Spawn : MonoBehaviour {

    public GameObject dice;
    public string isSleeping = ("");
    public bool mx = false;
    public string finalval;
    
    // Use this for initialization
    void Start ()
    {
    	dice = GameObject.Find("SixSidedDice");
    	dice.transform.position = new Vector3(0, 10, 0);
    	dice.transform.rotation = Random.rotation;
    }
    
    // Update is called once per frame
    void Update ()
    {
    	//Check if dice is moving
    	if (dice.rigidbody.velocity.x == 0.0 && dice.rigidbody.velocity.y == 0.0 && dice.rigidbody.velocity.z == 0.0)
    							
    		{
    		isSleeping = ("Sleep tight");	
    		
    		//print the dice outcome only once in Update via bool mx switch
    		if (!mx)
    			{
    				mx = true;
    				print (isSleeping);
    		//Find the Collision script and get the final value of the diceval variable
    		//If this is called in Start, diceval has no value because the cube has just been dropped
    			GameObject theValue = GameObject.Find("Floor");
    			Collision collisions = theValue.GetComponent<Collision>();
    			finalval = collisions.diceval;
    			
    				print (finalval);
    			}
    		}
    	}
    

    }

It might be crude code and solution, but I have the benefit of a beginner :slight_smile:

You should not compare floats against zero - as they will have rounding errors. Use should use the maths Epsilon function when checking the velocity of the rigidbody.