Adding plugins to your project is pretty straight forward as long as you know what folders you need to copy and where to.

  1. Go to your root project folder and create a Plugins folder if there isn’t one already
  2. Unzip the zip you downloaded for the  UXTools
    1. Navigate to the Plugins folder in the unzipped files. It will be something like >> MixedReality-UXTools-Unreal-public-0.11.x >> UXToolsGame >> Plugins >>
    2. Copy the folders named UXTools  to your project Plugins folder

     

And then the final thing is you need to go into Unreal and enable your plugins. In UE to Edit >> Plugins to bring up the Plugins Editor.

Scroll down to HoloLens and check Enabled

 

Next, ensure All is selected in the top left, and in the top right grey search box, type mixed to bring up all the Mixed Reality Plugins. Click the Enabled checkbox in the Microsoft Mixed Reality Plugins. You will be prompted to restart so go ahead and press the Restart Now button in the bottom right corner.

When you restart Unreal will build the UXTools into the project

 

 

When Unreal restarts the UXTools plugin will be in your Content Browser. If you can’t see them there (and I couldn’t when I first set up my file), you can display them by adjusting the Content Browser View Options. Select >> View Options >> Show Plugin Content. You can also Show C++ Classes, but for now turn everything else off otherwise you’ll have a tonne of folders to sift through.

 

<<<< STEP 2 – FILE SET UP         STEP 4 – CREATE A LEVEL >>>>

 

YOU have everything downloaded, now what?

Launch the Unreal Engine 4.26 from the Epic Games Launcher.

 

In the Select or Create New Project Window, select Games in the New Project Category section and then hit Next

 

 

Next select a Blank Template and then hit Next

 

 

And in the Project Settings Select C++ Project, Scalable 2D or 3D and Mobile/Tablet

Choose a name and where you want to save it.

Then hit Create Project

 

 

<<<< Step 1 SET UP        STEP 3 – ADDING PLUGINS >>>>

I am following the microsoft Chess app tutorial as I do this – adding in screen grabs for extra information for proper nubies, so for the original instructions go to microsoft
https://docs.microsoft.com/en-us/windows/mixed-reality/develop/unreal/tutorials/unreal-uxt-ch1

 

Before starting

 

have the following PROGRAMS installed.

HAVE THE FOLLOWING PLUGINS READY TO INSTALL

Download the following plugins so that you have them ready to copy to your Plugins folder once you have created your project. I’ll remind you later, but to find instructions on how to install plugins, see the Blog post titled Adding Plugins To Your Unreal Project

HAVE THE HOLOLENS 2 TARGET PLATFORM INSTALLED

To do this,

>> go to the Epic Games Launcher

>> click on the Library button at the top of the page

>>click on the arrow button next to launch on the 4.26.1 icon

>> go to options

 

>> scroll down until you get to the Target Platform section and ensure that Hololens 2 is ticked.

>> if it isn’t ticked, tick it and hit the apply button. The download will start for you.

STEP 2 – FILE SET UP >>>>

Set up your HoloLens to use the Windows Device Portal

 

Before accessing the Windows Device Portal, you need to set it up on HoloLens:
1. Put on your HoloLens device and turn on the power.
2. Do the bloom gesture to open the Start menu.
3. Go into Settings
4. Select the Update & Security menu item.
5. Select the For developers menu item.
6. Turn on Developer Mode.
7. Scroll down and turn on Enable Device Portal.

 

Using the Windows Device Portal - Mixed Reality | Microsoft Docs

 

Connect with Wi-Fi

  1. Connect your HoloLens to Wi-Fi.
  2. Look up your device’s IP address. – To find the IP address on the device, go to Settings > Network & Internet > Wi-Fi > Advanced Options. The IP address is the set of numbers given for IPv4 Address. It will be something like 192.168.1.147
  3. From a web browser on your PC, go to https://<YOUR_HOLOLENS_IP_ADDRESS>

You will receive a warning that Your connection isn’t private

 

Ignore it and hit the Advanced button

 

You’ll receive more warnings, ignore them and hit the continue to xxx.xx.xx.xxx (unsafe) link

 

 

You’ll be prompted to sign in. Use the Username (email) and password you signed into the device with, and then press the blue sign in button.

 

 

This will now load the Windows Device Portal to your Hololens.

 

 

Click on Views and Apps to load the app page.

 

 

Then click on the Choose File button to select your app to install

 

 

Navigate to where you have saved the Visual Studio Master Folder, select the YourAppNameMaster.apx file and hit open

 

 

It will start to upload to the Hololens

 

 

It will display  the message Package Successfully Registered when complete. Hit the Done button.

 

 

The App is now installed and ready to play on the Hololens 2. On  the Hololens Headset go into apps and select your app to load it.

 

 

 

 

NowSo I needed to create a Hololens 2 App and deploy it to an actual Hololens 2 that I had with me for development, AND I needed to save a copy of the compiled app that could be copied onto a Hololens 2 that my client had in another office. It was a very convoluted process so I thought I would document it now so I wouldn’t forget it for next time round.

 

Before you start make sure you have the following

Unity 2019.4.4f1 

MRTK 2.4.0 

Visual Studio 2019

 

The Best Tutorial on Set Up

I could go through and tell you how to create a Unity file that will run on the Hololens2, but really, just follow this one that Microsoft put out. It is the best.

https://docs.microsoft.com/en-us/windows/mixed-reality/develop/unity/tutorials/mr-learning-base-01

Just go through that page and you have set up your basic Unity MRTK file that compiles to the Hololens 2 through Visual Studio.

 

HOW TO CREATE A FILE TO SEND TO SOMEONE TO INSTALL

This is where is gets fiddly and you need to set up certificates and stuff. So…. let’s get started

 

In Unity, open your Player Settings File > Build Settings > Player Settings.

In the Player Settings Window Expand the Publishing Settings

Scroll down to  the Certificate section and click the Create… button

 

 

A pop up box will appear and ask you to fill in a Publisher (I usually put in either my client name or my Sole trader name), and a password. Do this and then click Create

 

 

Now go back to Visual Studio and in the Solution Explorer window expand your app and locate the Package.appxmanifest file. Click on it to open it.

 

 

Click on the Packaging heading and then click on the Choose Certificate button

 

 

Click on the Select from file… button

 

 

Navigate to  the Project Assets folder (make sure it’s not the Builds Asset folder!) and select the WSATestCertificate.pfx file

 

 

Now remember in Unity we gave the certificate a password, you’ll need to enter that now and press OK

 

Now click on View Full Certificate

 

 

And click on Install Certificate

 

Choose the Current User radio button and click Next

 

 

Choose the Place all certificates in the following store radio button and click Browse

 

 

Choose the Trusted Root Certification Authorities and click OK

 

 

Click Next

 

 

Click Finish

 

 

You’ll get a Security Warning. Click Yes

 

 

Then you’ll get a message that the Import Was Successful. Hit OK

 

 

And click OK

 

 

Now right click on your app in the Solution Explorer Your App > Publish > Create App Package

 

 

Select Distribution Method. Choose the sideloading radio button and click Next

 

 

Make sure the radio button Yes use the current certificate is selected and click Next

 

 

Hololens2 needs ARM64 so make sure that checkbox is selected also and hit Create

 

 

Navigate to the folder in Windows Explorer that you gave as your file path to save the packages, and you can send these to your tester to save onto their Hololens 2.

 

 

I have another blog post that shows you how to copy it onto your Hololens 2 here

 

 

using UnityEngine;
using UnityEngine.Windows.Speech;

public class SpeechRecogniser: MonoBehaviour
{
protected DictationRecognizer dictationRecognizer;

void Start()
{

}

// CALL THIS FUNCTION WHEN YOU WANT TO START LISTENING TO DICTATION
public void startDictationRequest(){

// THIS IS REALLY IMPORTANT!!
// If you are using the MRTK and have phrase recognition running, then you can't use both at once,
// so you need to turn it off with the following line
if (PhraseRecognitionSystem.Status == SpeechSystemStatus.Running)
{
PhraseRecognitionSystem.Shutdown();
}

StartDictationEngine();

}

// CALL THIS FUNCTION WHEN YOU WANT TO STOP LISTENING TO DICTATION
public void stopDictationRequest(){

// THIS IS REALLY IMPORTANT!!
// If you are using the MRTK and turned off phrase recognition to enable dictation
// you need to turn it back ON again with the following line
if (PhraseRecognitionSystem.Status != SpeechSystemStatus.Running)
{
PhraseRecognitionSystem.Restart();
}

CloseDictationEngine();
}

private void DictationRecognizer_OnDictationHypothesis(string text)
{

// So in here is the hypothesised text. It's quick, like as fast as it's spoken you'll get the string passed in here
// but it's slightly less accurate. So test what you get and see if it's close enough,
// otherwise do your checking for your phrases in the OnDictationResult method

if(text.Contains("your required phrase here")){
do something here
}
}

private void DictationRecognizer_OnDictationComplete(DictationCompletionCause completionCause)
{
switch (completionCause)
{
case DictationCompletionCause.TimeoutExceeded:
case DictationCompletionCause.PauseLimitExceeded:
case DictationCompletionCause.Canceled:
case DictationCompletionCause.Complete:
// Restart required
CloseDictationEngine();
StartDictationEngine();
break;
case DictationCompletionCause.UnknownError:
case DictationCompletionCause.AudioQualityFailure:
case DictationCompletionCause.MicrophoneUnavailable:
case DictationCompletionCause.NetworkFailure:
// Error
CloseDictationEngine();
break;
}
}

private void DictationRecognizer_OnDictationResult(string text, ConfidenceLevel confidence)
{

// Debug.Log("Dictation result: " + text);
if(text.Contains("in")){
messageText.text = "RESULT CONTAINS IN : " + text;
}else{
// Debug.Log("RESULT does not CONTAIN IN!!!");
}
}
private void DictationRecognizer_OnDictationError(string error, int hresult)
{
messageText.text = "Dictation error : " + error;
Debug.Log("Dictation error: " + error);
}
private void OnApplicationQuit()
{
CloseDictationEngine();
}
private void StartDictationEngine()
{
Debug.Log("StartDictationEngine");
dictationRecognizer = new DictationRecognizer();
dictationRecognizer.DictationHypothesis += DictationRecognizer_OnDictationHypothesis;
dictationRecognizer.DictationResult += DictationRecognizer_OnDictationResult;
dictationRecognizer.DictationComplete += DictationRecognizer_OnDictationComplete;
dictationRecognizer.DictationError += DictationRecognizer_OnDictationError;
dictationRecognizer.Start();
}
public void CloseDictationEngine()
{
if (dictationRecognizer != null)
{
dictationRecognizer.DictationHypothesis -= DictationRecognizer_OnDictationHypothesis;
dictationRecognizer.DictationComplete -= DictationRecognizer_OnDictationComplete;
dictationRecognizer.DictationResult -= DictationRecognizer_OnDictationResult;
dictationRecognizer.DictationError -= DictationRecognizer_OnDictationError;
if (dictationRecognizer.Status == SpeechSystemStatus.Running)
{
dictationRecognizer.Stop();
}
dictationRecognizer.Dispose();
}
}

Right, so classes have a number of methods in them and it can get a bit confusing as to when each of them are called, especially when you require a very specific sequence of events to occur.

So let’s say that you are instantiating a prefab from a class method.

 yourPrefab yPre = Instantiate(yourPrefab, transform.position, transform.rotation);
 
.SpawnAsteroid();
        ast.gameObject.name = "Asteroid_" + i.ToString("00");
        // Find a good location for the Asteroid to spawn
        Vector3 pos;
        do
        {
            pos = ScreenBounds.RANDOM_ON_SCREEN_LOC;
        } while ((pos - PlayerShip.POSITION).magnitude < MIN_ASTEROID_DIST_FROM_PLAYER_SHIP);

        ast.transform.position = pos;
        ast.size = asteroidsSO.initialSize;