Up to now in this series, I’ve added holograms to my scene within Unity. But it’s much more useful to be able to create holograms at run-time. This tutorial will show how to create a pre-fabricated object (called a prefab) in Unity, and how to use a simple tap gesture to add this hologram prefab to your scene.

Creating a pre-fabricated object in Unity

Unity has an asset type called prefab. This allows a GameObject to be created as a kind of global project asset which can be re-used numerous times in the project. Changing the prefab asset in one place also allows all instantiated occurences of the asset in your scene to change also.

Let’s create a simple object in a project hierarchy, and convert it to a prefab asset.

First, in a Unity project, right click on the Hierarchy surface and create a new Cube 3d object – call it “Cube”.

Next, right click on the Asset node in the Project surface, create a new material (the picture below shows how to select Material from the context menu). Call the material “Blue”.

screenshot.1469374606

For this material, selected the Albedo option and from colour chooser palette which appears, select a blue colour.

screenshot.1469374837

Now drag this material onto the “Cube” object in the Hierarchy view. The cube which is in the centre of the scene should now turn to a blue colour.

screenshot.1469375525

Next, right click on the Assets node in the Project view, and select the Create item in the context menu. From this, select the Prefab option.

screenshot.1469375699

Call this prefab object “BlueCube”. This will have the default icon of a white box.

screenshot.1469376023

If you now click on the Cube in the Hierarchy view, ou can drag this onto the BlueCube prefab object. The icon will change from a white box to a blue box, previewing what the object looks like in our virtual world.

screenshot.1469376154

You have now created a prefab object – whenever you want to create a BlueCube object like this in your scene, you can just use the prefab object, instead of having to create a cube and assign a material to it each time. Additionally, if you want to change the object in some way – for example to change the size, orientation, or shade of blue – you can change the prefab object, and this change will be reflected across all instantiations of this prefab.

How can we create a prefab hologram at runtime?

Let’s start by deleting the cube object from the scene. Either click on the cube in the scene, or click on the “Cube” object in the Hierarchy view, and hit delete. The scene will now be empty.

Now let’s create a new C# script to help us manage creating holograms. Right click on the Assets panel, and create a new C# script called “CubeManager”. Now double click on this script to open up your preferred script editor (e.g. MonoDevelop or Visual Studio).

There’s two things I want to do in this script – I need to capture a tap gesture, and when I detect a tap, I want to instantiate a “BlueCube” object 2m in front of where I’m presently looking.

First, add a public member GameObject variable to the CubeManager script called blueCubePrefab, as shown in the code below:

public class CubeManager : MonoBehaviour
{
    public GameObject blueCubePrefab;
}

Now we have to let our scene know about this script. Switch back to Unity, and right click on the Hierarchy panel – from the context menu, select “Create Empty”. Give this object the name “BlueCubeCollection”.

Drag the “CubeManager” C# script to the new “BlueCubeCollection” object. On the Inspector panel for the BlueCubeCollection object, you’ll see a new script property called “Cube Manager”.

screenshot.1469379685

Notice in the diagram above that the Cube Manager script has a variable called “Blue Cube Prefab”. Unity has created this property based on the public GameObject variable called “blueCubePrefab” in the C# script.

But also notice that the property has a value of “None” – whereas there’s a declaration, there’s no instantiation. We can fix this by dragging the BlueCube prefab we created earlier onto the textbox that says “None (Game Object)”. When you do this, the panel will change to look like the diagram below – notice that it now says “BlueCube” below.

screenshot.1469379987

Let’s go back to the C# script. In order to recognise gestures like a tap, the script needs to have a GestureRecognizer object. This object has an event called “TappedEvent”, and when this event is registered, we can start capturing gestures. The code below shows how this works.

using UnityEngine;
using UnityEngine.VR.WSA.Input;

public class CubeManager : MonoBehaviour
{
    public GameObject blueCubePrefab;
 
    GestureRecognizer recognizer;
 
    void Start()
    {
        recognizer = new GestureRecognizer();
 
        recognizer.TappedEvent += Recognizer_TappedEvent;
 
        recognizer.StartCapturingGestures();
    }
 
    private void Recognizer_TappedEvent(InteractionSourceKind source, int tapCount, Ray headRay)
    {
        // process the event.
    }

The last part of this is instantiating the new BlueCube object at a specific location. The key to this is the parameter headRay in the Recognizer_TappedEvent above. This headRay object has a couple of properties, which will help us position the new object – the properties are direction and origin. These are both of the type Vector3 – this object type is used for passing positions and directions.

  • headRay.origin gives us the position that the HoloLens wearer is at.
  • headRay.direction gives us the direction that the HoloLens wearer is looking.

Therefore, if we want to get the position 2m in front of the HoloLens, we can multiply the direction by 2, and add it to the origin value, like the code below:

var direction = headRay.direction;
 
var origin = headRay.origin;
 
var position = origin + direction * 2.0f;

So now we have the position where we want to place our hologram.

Finally, we just need the code to instantiate the blueCubeFab hologram. Fortunately, this is very easy.

Instantiate(blueCubePrefab, position, Quaternion.identity);

This call places an instance of the blueCubePrefab at the Vector3 position defined by position. The Quaternion.identity object simply means that the object is in the default rotation.

So the complete code for the CubeManager is below:

using UnityEngine;
using UnityEngine.VR.WSA.Input;

public class CubeManager : MonoBehaviour
{
    public GameObject blueCubePrefab;
 
    GestureRecognizer recognizer;
 
    void Start()
    {
        recognizer = new GestureRecognizer();
 
        recognizer.TappedEvent += Recognizer_TappedEvent;
 
        recognizer.StartCapturingGestures();
    }
 
    private void Recognizer_TappedEvent(InteractionSourceKind source, int tapCount, Ray headRay)
    {
        var direction = headRay.direction;
 
        var origin = headRay.origin;
 
        var position = origin + direction * 2.0f;
 
        Instantiate(blueCubePrefab, position, Quaternion.identity);
    }
}

Now we can build and run the project using the settings defined in my other post here. After running the project in Visual Studio through the HoloLens emulator which showed an empty scene, I created a few boxes (using the enter key to simulate an air-tap). I’ve navigated to the side to show these holograms.

screenshot.1469385281

So now we know how to create holograms at run-time from a prefabricated object using a gesture.

 

One thought on “Coding for the HoloLens with Unity 5 – Part #5: Creating holograms from prefabs at runtime using gestures

Comments are closed.