Tuesday, April 4, 2017

Unity3d creating a cube in c# with text on each side

I am currently exploring the power of the Unity3d developer environment. It really amazes me! Really fun and easy to get started and a lot of fun coding!
I wanted to create a cube with letters/text on each side. The text should be possible to manipulate dynamically so premade textures was out of the question.
First I thought that it couldn’t be so hard. I soon found out that many before me had struggled with the same problem.
I tried the 3dtext but it had a problem with the text showing througt other objects. Not very nice!
My solution is to use the UI and its text possibilities.
image
Create a method that takes the size of the cube and the text that should be printed on the side:
public class scriptCube {
  static GameObject addSide (int size, string text) {

First we create a canvas-object to hold the UI:

    GameObject mainObj = new GameObject();
    Canvas canvasObj = mainObj.AddComponent<Canvas>();
    canvasObj.renderMode = RenderMode.WorldSpace;

Then we create a rawimage-object and we connect it to the parent object:

    GameObject childObj2 = new GameObject ();
    RawImage rawimageObj = childObj2.AddComponent<RawImage>();
    rawimageObj.rectTransform.SetSizeWithCurrentAnchors
         (RectTransform.Axis.Horizontal, size);
    rawimageObj.rectTransform.SetSizeWithCurrentAnchors
         (RectTransform.Axis.Vertical, size);
    rawimageObj.color = Color.yellow;
    childObj2.transform.SetParent(mainObj.transform,false);


We also have to create the text-object and connect it to the parent object:
    GameObject childObj1 = new GameObject ();
    Text textObj = childObj1.AddComponent<Text>();
    textObj.font = (Font)Resources.GetBuiltinResource
        (typeof(Font), "Arial.ttf");;
    textObj.text = text;
    textObj.alignment = TextAnchor.MiddleCenter;
    textObj.enabled = true;
    textObj.fontSize = (int) (size*0.8);
    textObj.color = Color.black;
    textObj.rectTransform.SetSizeWithCurrentAnchors
        (RectTransform.Axis.Horizontal, size);
    textObj.rectTransform.SetSizeWithCurrentAnchors
        (RectTransform.Axis.Vertical, size);
    childObj1.transform.SetParent(mainObj.transform,false);


    return mainObj;
  }
}

Now that we have a method that creates panels with rawimages and text on it we need to put it all together with a method that create all sides of the cube and positions them correctly in the worldSpace.
The following code creates the six sides of the cube and positions and turns them individually.
I know this surely could be made in some more effective ways but this works for now.
public static GameObject createCube (string name, int size) {

  GameObject mainObj = new GameObject();
  mainObj.name = name;

  GameObject side1 = addSide (size, "1");
  side1.transform.SetParent (mainObj.transform);
  side1.transform.position = new Vector3(0,0,-size/2);
  side1.transform.rotation = Quaternion.Euler(0,0,0);

  GameObject side2 = addSide (size, "6");
  side2.transform.SetParent (mainObj.transform);
  side2.transform.position = new Vector3(0,0,size/2);
  side2.transform.rotation = Quaternion.Euler(0,180,0);

  GameObject side3 = addSide (size, "3");
  side3.transform.SetParent (mainObj.transform);
  side3.transform.position = new Vector3(0,-size/2,0);
  side3.transform.rotation = Quaternion.Euler(90,0,0);

  GameObject side4 = addSide (size, "4");
  side4.transform.SetParent (mainObj.transform);
  side4.transform.position = new Vector3(0,size/2,0);
  side4.transform.rotation = Quaternion.Euler(90,0,0);

  GameObject side5 = addSide (size, "2");
  side5.transform.SetParent (mainObj.transform);
  side5.transform.position = new Vector3(-size/2,0,0);
  side5.transform.rotation = Quaternion.Euler(0,90,0);

  GameObject side6 = addSide (size, "5");
  side6.transform.SetParent (mainObj.transform);
  side6.transform.position = new Vector3(size/2,0,0);
  side6.transform.rotation = Quaternion.Euler(0,270,0);

  mainObj.transform.rotation = Quaternion.Euler(45,45,45);

  return mainObj;
}

Add a call to the newly created method to get it all started:

void Start () {
  scriptCube scriptcube = new scriptCube ();
  GameObject cube = scriptCube.createCube ("Cube", 40);
}

To turn the scene camera to view the cube and rotate around it just add this to the camera script:
private GameObject target;
void Update () {
  target = GameObject.Find ("Cube");
  if (target != null) {
    transform.LookAt (target.transform);
    transform.Translate (Vector3.right * Time.deltaTime * 60);
  }
}

Happy hacking and have a nice day!