Anchoring your GameObjects in HoloLens apps

Happy 2019 all! I know it’s a tad bit late for that…

Have been trying to post something for a long time now and finally made it happen this week. In this article, you will learn how to create anchors for your holograms.

Think of an anchor as a static location in the real world for your hologram. You’ll need these for example when you return to your app and want your hologram/object to be in the same position where you put it the last time. Or you’ll need them when you don’t want your object to move.

Of course, Microsoft does a much better job of explaining how to use these and also recommends best practices for anchors, which I found extremely useful and which avoided some costly mistakes: https://docs.microsoft.com/en-us/windows/mixed-reality/spatial-anchors

With the help of the MRTK, anchoring and de-anchoring of objects is so easy, I was quite surprised…

So what we will do is, in our example, have a GameObject (can be anything- I use a simple Cube). Attach the HandDraggable.cs script to it from the HoloToolkit so that we test the moving and non-moving when the object is anchored.

We also will use speech commands to anchor an object and remove the anchor. We will also indicate some kind of visual feedback, for instance change the color of the Cube to red when it’s anchored and green when the anchor is released again.

Let’s start off with the usual things:

1. Create a new project. I have Unity version 2018.2.13f1

2. I’m using the latest stable release of the HoloToolkit 2017.4.3.0 Import it into your project

3. Do the usual tweaks:

a. Delete the main Camera.  Add the MixedRealityCameraParent.prefab in the Hierarchy. This will serve as the Main Camera

b. Change the Camera Settings to Hololens preferred:

Skybox to Solid Color

Background to 0,0,0,0

In the MixedRealityCameraManager script which is attached to the MixedRealityCamera object, change the Clear Flags value to Solid Color

Ensure that the Background Color is black

c. Go to Edit ->Project Settings -> Player -> Other Settings -> and change the Scripting Runtime version to .NET 4.x Equivalent and Scripting Backend to .Net

Make sure also that in XR Settings, Virtual Reality Supported is checked

We need both the InputManager and the DefaultCursor in the scene because we will be using HandDraggable and SpeechInput.

4. InputManager

Drag and drop the InputManager.prefab into your scene

5. DefaultCursor

Drag and drop the DefaultCursor.prefab into your scene. In the InputManager’s Inspector Settings, drag and drop the DefaultCursor into the Cursor field of the SimpleSinglePointerSelector script

d. Save the scene

Now let’s add the Cube to our project:

We will move this, anchor and de-anchor it.

Let’s go ahead and add the HandDraggable script to the Cube. I have explained this in more detail in my tutorial to move objects: https://codeholo.com/2018/05/06/move-resize-and-rotate-objects-in-your-hololens-apps/

Make sure your Cube has a collider. Because you need this to move the objects and  Normally, this is existing by default when you add the Cube to the scene.

 Now let's add the Cube to our project. We will move this, anchor and de-anchor it. Let's go ahead and add the HandDraggable.cs script to the Cube. I have explained this in more detail in my tutorial to move objects: https://codeholo.com/2018/05/06/move-resize-and-rotate-objects-in-your-hololens-apps/ Make sure your Cube has a collider. Because you need this to move the objects and Normally, this is existing by default when you add the Cube to the scene.

Next let’s write a simple script to do our Anchoring part:

First, we need to use the WorldAnchorManager script within the HoloToolkit. This makes our life easy. Create an empty GameObject. Rename it Managers or something similar.

I like to organize – so we will create another empty child GameObject to the Managers and call it AnchorManager. On it’s Add Component, add the WorldAnchorManager script from the MRTK to the Managers GameObject. We will also move the InputManager to the Managers just to stay further organized.

This script has certain Inspector elements. What we need to check is the PersistentAnchors checkbox- since we need our Cube to be anchored even when we exit our app and restart it.

 Next let's write a simple script to do our Anchoring part: First, we need to use the WorldAnchorManager script within the HoloToolkit. This makes our life easy. Create an empty GameObject. Rename it Managers or something similar. I like to organize - so we will create another empty child GameObject to the Managers and call it AnchorManager. On it's Add Component, add the WorldAnchorManager script from the MRTK to the Managers GameObject. We will also move the InputManager to the Managers just to stay further organized. This script has certain Inspector elements. What we need to check is the PersistentAnchors checkbox- since we need our Cube to be anchored even when we exit our app and restart it.

Now come back to the Cube and we will write a simple script to execute anchoring and release when we want it to:

On the Cube, click on Add Component and add a new script. Call it AnchorScript or something relevant.

Edit this script in Visual Studio. We will write two functions – one to execute anchor and the other to release it.

First we have to reference our WorldAnchorManager in the scene. Let’s create a public variable to hold the WorldAnchorManager. The script will complain that this cannot be found, so you need to add the using directive using HoloToolkit.Unity to it.

Next we add a function AnchorIt() where we would write our code to anchor the Cube and also change it’s color to red after anchoring.

You just need to include this line:

worldAnchorManager.AttachAnchor(this.gameObject);

This will create an anchor of the name Cube in the WorldAnchorStore. This can be retrieved later automatically, even when we restart app (because we checked persistent anchors).

Include the code to change the color to red.

Now for our function to remove the anchor:

In the function (I call it ReleaseAnchor), simply call the line:

worldAnchorManager.RemoveAnchor(this.gameObject);

Include the code to change the color to green.

Now one important part:

We need to include a Start() and call AnchorIt() from there. This ensures that everytime you restart the app, the WorldAnchorStore loads the anchors of the GameObject to which you are referencing to and anchors it in the approximate position in the world space. The first time you do this, the Cube would be anchored as soon as you start the app.Just say “Release” to remove the anchor.

The complete script screenshot is shown below:

Don’t forget to now go back to the Inspector settings of the AnchorScript and add the WorldAnchorManager in the scene.

 Don't forget to now go back to the Inspector settings of the AnchorScript and add the WorldAnchorManager in the scene.

Let’s add the final part for the speech commands:

Under Managers, create an empty Child object and call it SpeechManager. To the SpeechManager, add the Speech Input Source and the Speech Input Handler. (I have explained how to use speech commands in detail in the tutorial: https://codeholo.com/2017/12/03/how-to-use-voice-input-in-hololens/)

Under the Speech Input Source, add the keywords “Anchor” and “Release“.

Under the Speech Input Handler, add the method AnchorIt() for the speech command Anchor, and the method RemoveAnchor() for the speech command Release.

Don’t forget to check the capability Microphone” in Publishing Settings.

 Let's add the final part for the speech commands: Under Managers, create an empty Child object and call it SpeechManager. To the SpeechManager, add the Speech Input Source and the Speech Input Handler. (I have explained how to use speech commands in detail in the tutorial: https://codeholo.com/2017/12/03/how-to-use-voice-input-in-hololens/) Under the Speech Input Source, add the keywords Anchor and Release. Under the Speech Input Handler, add the method AnchorIt() for the speech command Anchor, and the method RemoveAnchor() for the speech command Release. Don't forget to check the capability Microphone in Publishing Settings.

Before we build and deploy, let’s adjust our camera to see the cube. Let’s also make the cube slightly smaller so that we can see better. I changed the Cube scale to 0.2,0.2,0.2.

Delete the annoying TextMeshPro package before you build. (If you get the TextMeshPro error while deploying, then remove the package Unity TextMeshPro from your project and rebuild. Go to Unity->Window->Package Manager and a pop up appears.Click on TextMeshPro and Remove. While you are at it, also remove the Analytics Library, Ads and In App purchasing)

Deploy onto the HoloLens. Accept the popup which asks you to use the Microphone.

The first time you do this, the Cube would be anchored as soon as you start the app.Just say “Release” to remove the anchor.

So you should be able to first move the Cube using dragging gesture (also explained in a full tutorial https://codeholo.com/2018/05/06/move-resize-and-rotate-objects-in-your-hololens-apps/)

Then you say, “Anchor” and the Cube remains in that location and turns red. You should no longer be able to move the Cube.

Next, you should close the app and restart it. Once you restart, the Cube should be in that approximate position where you last left it.  (Tip: to effectively restart the app, make sure you close the window and restart and see the “Made with Unity” splash screen)

Now say “Release”. The Cube should now turn green and be draggable again.

If you also turn on the Debugging mode, you’ll see logs in the Output where WorldanchorStore has attached and released anchors and it says whether it was successful or had a problem etc.

A video of the expected output is shown below:

That’s it! Let me know if you have any question/feedback for the Anchor example tutorial.

Errors and solutions:

Error 1: The Cube does not move

Solution: possibly missing a Collider, or Cursor or InputManager

Error 2: When you say Anchor, nothing happens.

Solution: Check if the Inspector Settings of the AnchorScript has a reference to the WorldAnchorManager in your scene.

Check if the speech commands, Anchor is added and subsequently, the method AnchorIt() is added.

Check if the capability Microphone is enabled

Leave a Reply

Your email address will not be published. Required fields are marked *

%d bloggers like this: