Step 4
Step 4
Troubleshooting
You want to ensure the following criteria below are met, if you are having trouble connecting the Hololens
using UnityEngine; public class WorldCursor : MonoBehaviour { private MeshRenderer meshRenderer; // Use this for initialization void Start() { // Grab the mesh renderer that's on the same object as this script. meshRenderer = this.gameObject.GetComponentInChildren<MeshRenderer>(); } // Update is called once per frame void Update() { // Do a raycast into the world based on the user's // head position and orientation. var headPosition = Camera.main.transform.position; var gazeDirection = Camera.main.transform.forward; RaycastHit hitInfo; if (Physics.Raycast(headPosition, gazeDirection, out hitInfo)) { // If the raycast hit a hologram... // Display the cursor mesh. meshRenderer.enabled = true; // Move the cursor to the point where the raycast hit. this.transform.position = hitInfo.point; // Rotate the cursor to hug the surface of the hologram. this.transform.rotation = Quaternion.FromToRotation(Vector3.up, hitInfo.normal); } else { // If the raycast did not hit a hologram, hide the cursor mesh. meshRenderer.enabled = false; } } }
using UnityEngine; using UnityEngine.XR.WSA.Input; public class GazeGestureManager : MonoBehaviour { public static GazeGestureManager Instance { get; private set; } // Represents the hologram that is currently being gazed at. public GameObject FocusedObject { get; private set; } GestureRecognizer recognizer; // Use this for initialization void Awake() { Instance = this; // Set up a GestureRecognizer to detect Select gestures. recognizer = new GestureRecognizer(); recognizer.Tapped += (args) => { // Send an OnSelect message to the focused object and its ancestors. if (FocusedObject != null) { FocusedObject.SendMessageUpwards("OnSelect", SendMessageOptions.DontRequireReceiver); } }; recognizer.StartCapturingGestures(); } // Update is called once per frame void Update() { // Figure out which hologram is focused this frame. GameObject oldFocusObject = FocusedObject; // Do a raycast into the world based on the user's // head position and orientation. var headPosition = Camera.main.transform.position; var gazeDirection = Camera.main.transform.forward; RaycastHit hitInfo; if (Physics.Raycast(headPosition, gazeDirection, out hitInfo)) { // If the raycast hit a hologram, use that as the focused object. FocusedObject = hitInfo.collider.gameObject; } else { // If the raycast did not hit a hologram, clear the focused object. FocusedObject = null; } // If the focused object changed this frame, // start detecting fresh gestures again. if (FocusedObject != oldFocusObject) { recognizer.CancelGestures(); recognizer.StartCapturingGestures(); } } }
using UnityEngine; public class SphereCommands : MonoBehaviour { // Called by GazeGestureManager when the user performs a Select gesture void OnSelect() { // If the sphere has no Rigidbody component, add one to enable physics. if (!this.GetComponent<Rigidbody>()) { var rigidbody = this.gameObject.AddComponent<Rigidbody>(); rigidbody.collisionDetectionMode = CollisionDetectionMode.Continuous; } } }
using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.Windows.Speech; public class SpeechManager : MonoBehaviour { KeywordRecognizer keywordRecognizer = null; Dictionary<string, System.Action> keywords = new Dictionary<string, System.Action>(); // Use this for initialization void Start() { keywords.Add("Reset world", () => { // Call the OnReset method on every descendant object. this.BroadcastMessage("OnReset"); }); keywords.Add("Drop Sphere", () => { var focusObject = GazeGestureManager.Instance.FocusedObject; if (focusObject != null) { // Call the OnDrop method on just the focused object. focusObject.SendMessage("OnDrop", SendMessageOptions.DontRequireReceiver); } }); // Tell the KeywordRecognizer about our keywords. keywordRecognizer = new KeywordRecognizer(keywords.Keys.ToArray()); // Register a callback for the KeywordRecognizer and start recognizing! keywordRecognizer.OnPhraseRecognized += KeywordRecognizer_OnPhraseRecognized; keywordRecognizer.Start(); } private void KeywordRecognizer_OnPhraseRecognized(PhraseRecognizedEventArgs args) { System.Action keywordAction; if (keywords.TryGetValue(args.text, out keywordAction)) { keywordAction.Invoke(); } } }
using UnityEngine; public class SphereCommands : MonoBehaviour { Vector3 originalPosition; // Use this for initialization void Start() { // Grab the original local position of the sphere when the app starts. originalPosition = this.transform.localPosition; } // Called by GazeGestureManager when the user performs a Select gesture void OnSelect() { // If the sphere has no Rigidbody component, add one to enable physics. if (!this.GetComponent<Rigidbody>()) { var rigidbody = this.gameObject.AddComponent<Rigidbody>(); rigidbody.collisionDetectionMode = CollisionDetectionMode.Continuous; } } // Called by SpeechManager when the user says the "Reset world" command void OnReset() { // If the sphere has a Rigidbody component, remove it to disable physics. var rigidbody = this.GetComponent<Rigidbody>(); if (rigidbody != null) { rigidbody.isKinematic = true; Destroy(rigidbody); } // Put the sphere back into its original local position. this.transform.localPosition = originalPosition; } // Called by SpeechManager when the user says the "Drop sphere" command void OnDrop() { // Just do the same logic as a Select gesture. OnSelect(); } }
using UnityEngine; public class SphereSounds : MonoBehaviour { AudioSource impactAudioSource = null; AudioSource rollingAudioSource = null; bool rolling = false; void Start() { // Add an AudioSource component and set up some defaults impactAudioSource = gameObject.AddComponent<AudioSource>(); impactAudioSource.playOnAwake = false; impactAudioSource.spatialize = true; impactAudioSource.spatialBlend = 1.0f; impactAudioSource.dopplerLevel = 0.0f; impactAudioSource.rolloffMode = AudioRolloffMode.Logarithmic; impactAudioSource.maxDistance = 20f; rollingAudioSource = gameObject.AddComponent<AudioSource>(); rollingAudioSource.playOnAwake = false; rollingAudioSource.spatialize = true; rollingAudioSource.spatialBlend = 1.0f; rollingAudioSource.dopplerLevel = 0.0f; rollingAudioSource.rolloffMode = AudioRolloffMode.Logarithmic; rollingAudioSource.maxDistance = 20f; rollingAudioSource.loop = true; // Load the Sphere sounds from the Resources folder impactAudioSource.clip = Resources.Load<AudioClip>("Impact"); rollingAudioSource.clip = Resources.Load<AudioClip>("Rolling"); } // Occurs when this object starts colliding with another object void OnCollisionEnter(Collision collision) { // Play an impact sound if the sphere impacts strongly enough. if (collision.relativeVelocity.magnitude >= 0.1f) { impactAudioSource.Play(); } } // Occurs each frame that this object continues to collide with another object void OnCollisionStay(Collision collision) { Rigidbody rigid = gameObject.GetComponent<Rigidbody>(); // Play a rolling sound if the sphere is rolling fast enough. if (!rolling && rigid.velocity.magnitude >= 0.01f) { rolling = true; rollingAudioSource.Play(); } // Stop the rolling sound if rolling slows down. else if (rolling && rigid.velocity.magnitude < 0.01f) { rolling = false; rollingAudioSource.Stop(); } } // Occurs when this object stops colliding with another object void OnCollisionExit(Collision collision) { // Stop the rolling sound if the object falls off and stops colliding. if (rolling) { rolling = false; impactAudioSource.Stop(); rollingAudioSource.Stop(); } } }
using UnityEngine; public class TapToPlaceParent : MonoBehaviour { bool placing = false; // Called by GazeGestureManager when the user performs a Select gesture void OnSelect() { // On each Select gesture, toggle whether the user is in placing mode. placing = !placing; // If the user is in placing mode, display the spatial mapping mesh. if (placing) { SpatialMapping.Instance.DrawVisualMeshes = true; } // If the user is not in placing mode, hide the spatial mapping mesh. else { SpatialMapping.Instance.DrawVisualMeshes = false; } } // Update is called once per frame void Update() { // If the user is in placing mode, // update the placement to match the user's gaze. if (placing) { // Do a raycast into the world that will only hit the Spatial Mapping mesh. var headPosition = Camera.main.transform.position; var gazeDirection = Camera.main.transform.forward; RaycastHit hitInfo; if (Physics.Raycast(headPosition, gazeDirection, out hitInfo, 30.0f, SpatialMapping.PhysicsRaycastMask)) { // Move this object's parent object to // where the raycast hit the Spatial Mapping mesh. this.transform.parent.position = hitInfo.point; // Rotate this object's parent object to face the user. Quaternion toQuat = Camera.main.transform.localRotation; toQuat.x = 0; toQuat.z = 0; this.transform.parent.rotation = toQuat; } } } }
using UnityEngine; public class HitTarget : MonoBehaviour { // These public fields become settable properties in the Unity editor. public GameObject underworld; public GameObject objectToHide; // Occurs when this object starts colliding with another object void OnCollisionEnter(Collision collision) { // Hide the stage and show the underworld. objectToHide.SetActive(false); underworld.SetActive(true); // Disable Spatial Mapping to let the spheres enter the underworld. SpatialMapping.Instance.MappingEnabled = false; } }