HoloLens (1e generatie) en Azure 312: Bot-integratie
Notitie
De Mixed Reality Academy-zelfstudies zijn ontworpen met HoloLens (1e generatie) en Mixed Reality Immersive Headsets in gedachten. Daarom vinden we het belangrijk om deze zelfstudies te behouden voor ontwikkelaars die nog steeds op zoek zijn naar richtlijnen bij het ontwikkelen voor die apparaten. Deze zelfstudies worden niet bijgewerkt met de nieuwste toolsets of interacties die worden gebruikt voor HoloLens 2. Ze blijven behouden om door te gaan met het werken op de ondersteunde apparaten. Er is een nieuwe reeks zelfstudies die in de toekomst zullen worden gepost en die laten zien hoe u zich ontwikkelt voor HoloLens 2. Deze kennisgeving wordt bijgewerkt met een koppeling naar deze zelfstudies wanneer ze worden gepost.
In deze cursus leert u hoe u een bot maakt en implementeert met behulp van Microsoft Bot Framework V4 en ermee communiceert via een Windows Mixed Reality-toepassing.
Microsoft Bot Framework V4 is een set API's die zijn ontworpen om ontwikkelaars de hulpprogramma's te bieden voor het bouwen van een uitbreidbare en schaalbare bottoepassing. Ga naar de microsoft Bot Framework-pagina of de V4 Git-opslagplaats voor meer informatie.
Nadat u deze cursus hebt voltooid, hebt u een Windows Mixed Reality-toepassing gemaakt, die het volgende kan doen:
- Gebruik een tikbeweging om de bot te starten die luistert naar de stem van de gebruikers.
- Wanneer de gebruiker iets heeft gezegd, probeert de bot een antwoord te geven.
- Geef de bots weer als tekst, in de buurt van de bot, in de Unity-scène.
In uw toepassing is het aan u om te bepalen hoe u de resultaten integreert met uw ontwerp. Deze cursus is ontworpen om u te leren hoe u een Azure Service integreert met uw Unity-project. Het is uw taak om de kennis die u uit deze cursus krijgt te gebruiken om uw mixed reality-toepassing te verbeteren.
Ondersteuning voor apparaten
Cursus | HoloLens | Insluitende headsets |
---|---|---|
MR en Azure 312: Bot-integratie | ✔️ | ✔️ |
Notitie
Hoewel deze cursus voornamelijk gericht is op HoloLens, kunt u ook toepassen wat u in deze cursus leert op Vr-headsets (Windows Mixed Reality immersive). Omdat insluitende headsets (VR) geen toegankelijke camera's hebben, hebt u een externe camera nodig die is aangesloten op uw pc. Terwijl u de cursus volgt, ziet u notities over eventuele wijzigingen die u mogelijk moet gebruiken om insluitende headsets (VR) te ondersteunen.
Vereisten
Notitie
Deze zelfstudie is ontworpen voor ontwikkelaars die basiservaring hebben met Unity en C#. Houd er ook rekening mee dat de vereisten en schriftelijke instructies in dit document staan voor wat er op het moment van schrijven is getest en geverifieerd (juli 2018). U bent vrij om de nieuwste software te gebruiken, zoals vermeld in het artikel over de installatie van de hulpprogramma's , hoewel wordt ervan uitgegaan dat de informatie in deze cursus perfect overeenkomt met wat u vindt in nieuwere software dan hieronder wordt vermeld.
Voor deze cursus raden we de volgende hardware en software aan:
- Een ontwikkel-pc, compatibel met Windows Mixed Reality voor insluitende headsetontwikkeling (VR)
- Windows 10 Fall Creators Update (of hoger) waarvoor de ontwikkelaarsmodus is ingeschakeld
- De nieuwste Windows 10 SDK
- Unity 2017.4
- Visual Studio 2017
- Een Windows Mixed Reality immersive (VR)-headset of Microsoft HoloLens waarvoor de ontwikkelaarsmodus is ingeschakeld
- Internettoegang voor Azure en voor ophalen van Azure-bot. Volg deze koppeling voor meer informatie.
Voordat u begint
- Om problemen met het bouwen van dit project te voorkomen, wordt u sterk aangeraden het project te maken dat in deze zelfstudie wordt genoemd in een hoofdmap of in een near-rootmap (lange mappaden kunnen problemen veroorzaken tijdens de build).
- Uw HoloLens instellen en testen. Als u ondersteuning nodig hebt voor het instellen van uw HoloLens, gaat u naar het installatieartikel van HoloLens.
- Het is een goed idee om kalibratie en sensorafstemming uit te voeren bij het ontwikkelen van een nieuwe HoloLens-app (soms kan het helpen om deze taken voor elke gebruiker uit te voeren).
Voor hulp bij kalibratie volgt u deze koppeling naar het HoloLens-kalibratieartikel.
Volg deze koppeling naar het artikel HoloLens Sensor Tuning voor hulp bij sensorafstemming.
Hoofdstuk 1: De bottoepassing maken
De eerste stap is het maken van uw bot als een lokale ASP.Net Core-webtoepassing. Zodra u klaar bent en getest, publiceert u deze naar Azure Portal.
Open Visual Studio. Maak een nieuw project, selecteer ASP NET Core Web Application als het projecttype (u vindt het onder de subsectie .NET Core) en noem het MyBot. Klik op OK.
Selecteer Leeg in het venster dat wordt weergegeven. Zorg er ook voor dat het doel is ingesteld op ASP NET Core 2.0 en dat de verificatie is ingesteld op Geen verificatie. Klik op OK.
De oplossing wordt nu geopend. Klik met de rechtermuisknop op Solution Mybot in Solution Explorer en klik op NuGet-pakketten voor oplossing beheren.
Zoek op het tabblad Bladeren naar Microsoft.Bot.Builder.Integration.AspNet.Core (zorg ervoor dat vooraf release opnemen is ingeschakeld). Selecteer de pakketversie 4.0.1-preview en schakel de projectvakken in. Klik vervolgens op Installeren. U hebt nu de bibliotheken geïnstalleerd die nodig zijn voor Bot Framework v4. Sluit de NuGet-pagina.
Klik met de rechtermuisknop op uw project, MyBot, in Solution Explorer en klik op Klasse toevoegen |.
Noem de klasse MyBot en klik op Toevoegen.
Herhaal het vorige punt om een andere klasse met de naam ConversationContext te maken.
Klik met de rechtermuisknop op wwwroot in Solution Explorer en klik op Nieuw item toevoegen | . Selecteer HTML-pagina (u vindt deze onder het subsectieweb). Geef het bestand een naam default.html. Klik op Toevoegen.
De lijst met klassen/objecten in Solution Explorer moet eruitzien zoals in de onderstaande afbeelding.
Dubbelklik op de conversationcontext-klasse . Deze klasse is verantwoordelijk voor het bewaren van de variabelen die door de bot worden gebruikt om de context van het gesprek te behouden. Deze gesprekscontextwaarden worden bijgehouden in een exemplaar van deze klasse, omdat elk exemplaar van de klasse MyBot telkens wordt vernieuwd wanneer een activiteit wordt ontvangen. Voeg de volgende code toe aan de klasse :
namespace MyBot { public static class ConversationContext { internal static string userName; internal static string userMsg; } }
Dubbelklik op de klasse MyBot . Deze klasse host de handlers die worden aangeroepen door binnenkomende activiteiten van de klant. In deze klasse voegt u de code toe die wordt gebruikt om het gesprek tussen de bot en de klant te bouwen. Zoals eerder vermeld, wordt een exemplaar van deze klasse geïnitialiseerd telkens wanneer een activiteit wordt ontvangen. Voeg de volgende code toe aan deze klasse:
using Microsoft.Bot; using Microsoft.Bot.Builder; using Microsoft.Bot.Schema; using System.Threading.Tasks; namespace MyBot { public class MyBot : IBot { public async Task OnTurn(ITurnContext context) { ConversationContext.userMsg = context.Activity.Text; if (context.Activity.Type is ActivityTypes.Message) { if (string.IsNullOrEmpty(ConversationContext.userName)) { ConversationContext.userName = ConversationContext.userMsg; await context.SendActivity($"Hello {ConversationContext.userName}. Looks like today it is going to rain. \nLuckily I have umbrellas and waterproof jackets to sell!"); } else { if (ConversationContext.userMsg.Contains("how much")) { if (ConversationContext.userMsg.Contains("umbrella")) await context.SendActivity($"Umbrellas are $13."); else if (ConversationContext.userMsg.Contains("jacket")) await context.SendActivity($"Waterproof jackets are $30."); else await context.SendActivity($"Umbrellas are $13. \nWaterproof jackets are $30."); } else if (ConversationContext.userMsg.Contains("color") || ConversationContext.userMsg.Contains("colour")) { await context.SendActivity($"Umbrellas are black. \nWaterproof jackets are yellow."); } else { await context.SendActivity($"Sorry {ConversationContext.userName}. I did not understand the question"); } } } else { ConversationContext.userMsg = string.Empty; ConversationContext.userName = string.Empty; await context.SendActivity($"Welcome! \nI am the Weather Shop Bot \nWhat is your name?"); } } } }
Dubbelklik op de opstartklasse . Met deze klasse wordt de bot geïnitialiseerd. Voeg de volgende code toe aan de klasse :
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Bot.Builder.BotFramework; using Microsoft.Bot.Builder.Integration.AspNet.Core; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; namespace MyBot { public class Startup { public IConfiguration Configuration { get; } public Startup(IHostingEnvironment env) { var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) .AddEnvironmentVariables(); Configuration = builder.Build(); } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddSingleton(_ => Configuration); services.AddBot<MyBot>(options => { options.CredentialProvider = new ConfigurationCredentialProvider(Configuration); }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseDefaultFiles(); app.UseStaticFiles(); app.UseBotFramework(); } } }
Open het klassebestand Program en controleer of de code in het bestand hetzelfde is als het volgende:
using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; namespace MyBot { public class Program { public static void Main(string[] args) { BuildWebHost(args).Run(); } public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>() .Build(); } }
Vergeet niet om uw wijzigingen op te slaan. Ga hiervoor naar Bestand>opslaan alles vanaf de werkbalk boven aan Visual Studio.
Hoofdstuk 2: De Azure Bot Service maken
Nu u de code voor uw bot hebt gebouwd, moet u deze publiceren naar een exemplaar van de Web App Bot Service in Azure Portal. In dit hoofdstuk ziet u hoe u de Bot Service in Azure maakt en configureert en vervolgens uw code ernaar publiceert.
Meld u eerst aan bij Azure Portal (https://portal.azure.com).
- Als u nog geen Azure-account hebt, moet u er een maken. Als u deze zelfstudie volgt in een leslokaal- of labsituatie, vraagt u uw docent of een van de proctors voor hulp bij het instellen van uw nieuwe account.
Zodra u bent aangemeld, klikt u op Een resource maken in de linkerbovenhoek en zoekt u naar web-app-bot en klikt u op Enter.
De nieuwe pagina bevat een beschrijving van de web-app-botservice . Selecteer linksonder op deze pagina de knop Maken om een koppeling met deze service te maken.
Zodra u op Maken hebt geklikt:
Voeg de gewenste naam in voor dit service-exemplaar.
Selecteer een abonnement.
Kies een resourcegroep of maak een nieuwe. Een resourcegroep biedt een manier om de toegang te bewaken, te beheren, facturering in te richten en te beheren voor een verzameling Azure-assets. Het wordt aanbevolen om alle Azure-services die zijn gekoppeld aan één project (bijvoorbeeld deze cursussen) onder een gemeenschappelijke resourcegroep te houden.
Als u meer wilt weten over Azure-resourcegroepen, volgt u deze koppeling
Bepaal de locatie voor uw resourcegroep (als u een nieuwe resourcegroep maakt). De locatie zou zich idealiter in de regio bevinden waar de toepassing zou worden uitgevoerd. Sommige Azure-assets zijn alleen beschikbaar in bepaalde regio's.
Selecteer de prijscategorie die geschikt is voor u, als dit de eerste keer is dat u een Web App Bot Service maakt, moet er een gratis laag (met de naam F0) beschikbaar zijn voor u
De naam van de app kan gewoon hetzelfde blijven als de botnaam.
Laat de botsjabloon op Basis (C#) staan.
App Service-plan/-locatie moet automatisch zijn ingevuld voor uw account.
Stel de Azure Storage in die u wilt gebruiken om uw bot te hosten. Als u er nog geen hebt, kunt u deze hier maken.
U moet ook bevestigen dat u de voorwaarden hebt begrepen die op deze Service zijn toegepast.
Klik op Create.
Nadat u op Maken hebt geklikt, moet u wachten totdat de service is gemaakt. Dit kan een minuut duren.
Er wordt een melding weergegeven in de portal zodra het service-exemplaar is gemaakt.
Klik op de melding om uw nieuwe service-exemplaar te verkennen.
Klik op de knop Ga naar de resource in de melding om uw nieuwe service-exemplaar te verkennen. U wordt naar uw nieuwe Azure Service-exemplaar gebracht.
Op dit moment moet u een functie met de naam Direct Line instellen, zodat uw clienttoepassing kan communiceren met deze Bot Service. Klik op Kanalen en klik vervolgens in de sectie Een aanbevolen kanaal toevoegen op Direct Line-kanaal configureren.
Op deze pagina vindt u de geheime sleutels waarmee uw client-app kan worden geverifieerd bij de bot. Klik op de knop Weergeven en neem een kopie van een van de weergegeven sleutels, omdat u dit later in uw project nodig hebt.
Hoofdstuk 3: de bot publiceren naar de Azure Web App Bot Service
Nu uw service klaar is, moet u uw botcode publiceren, die u eerder hebt gemaakt, naar de zojuist gemaakte Web App Bot Service.
Notitie
Telkens wanneer u wijzigingen aanbrengt in de botoplossing/code, moet u uw bot publiceren naar de Azure-service.
Ga terug naar uw Visual Studio Solution die u eerder hebt gemaakt.
Klik met de rechtermuisknop op uw MyBot-project in Solution Explorer en klik vervolgens op Publiceren.
Klik op de pagina Een publicatiedoel kiezen op App Service en klik vervolgens op Bestaand selecteren en klik ten slotte op Profiel maken (mogelijk moet u naast de knop Publiceren op de vervolgkeuzepijl klikken als dit niet zichtbaar is).
Als u nog niet bent aangemeld bij uw Microsoft-account, moet u dit hier doen.
Op de pagina Publiceren moet u hetzelfde abonnement instellen dat u hebt gebruikt voor het maken van de web-app-botservice . Stel vervolgens de weergave in als resourcegroep en selecteer in de vervolgkeuzelijst de resourcegroep die u eerder hebt gemaakt. Klik op OK.
Klik nu op de knop Publiceren en wacht tot de bot is gepubliceerd (dit kan enkele minuten duren).
Hoofdstuk 4 – Het Unity-project instellen
Hier volgt een typische opzet voor het ontwikkelen met mixed reality en is als zodanig een goede sjabloon voor andere projecten.
Open Unity en klik op Nieuw.
U moet nu een Unity-projectnaam opgeven. HoloLens-bot invoegen. Zorg ervoor dat de projectsjabloon is ingesteld op 3D. Stel de locatie in op een locatie die geschikt is voor u (vergeet niet, dichter bij hoofdmappen is beter). Klik vervolgens op Project maken.
Als Unity is geopend, is het de moeite waard om te controleren of de standaardscripteditor is ingesteld op Visual Studio. Ga naar Voorkeuren bewerken > en navigeer vervolgens vanuit het nieuwe venster naar Externe hulpprogramma's. Wijzig de externe scripteditor in Visual Studio 2017. Sluit het venster Voorkeuren .
Ga vervolgens naar Instellingen voor bestandsbuild > en selecteer Universeel Windows-platform en klik vervolgens op de knop Platform wisselen om uw selectie toe te passen.
Terwijl u zich nog steeds in de instellingen voor het > bouwen van bestanden houdt en controleert u of:
Doelapparaat is ingesteld op HoloLens
Voor de insluitende headsets stelt u Doelapparaat in op Elk apparaat.
Buildtype is ingesteld op D3D
SDK is ingesteld op Laatst geïnstalleerd
Visual Studio-versie is ingesteld op Meest recent geïnstalleerd
Bouwen en uitvoeren is ingesteld op lokale computer
Sla de scène op en voeg deze toe aan de build.
Doe dit door Open Scènes toevoegen te selecteren. Er wordt een venster voor opslaan weergegeven.
Maak hiervoor een nieuwe map, en voor elke toekomst scène, selecteer vervolgens de knop Nieuwe map om een nieuwe map te maken, geef deze de naam Scènes.
Open de zojuist gemaakte map Scènes en klik vervolgens in de bestandsnaam: tekstveld, typ BotScene en klik vervolgens op Opslaan.
De overige instellingen, in Build-instellingen, moeten voorlopig standaard blijven staan.
Klik in het venster Build-instellingen op de knop Spelerinstellingen . Hiermee opent u het gerelateerde deelvenster in de ruimte waar de Inspector zich bevindt.
In dit deelvenster moeten enkele instellingen worden geverifieerd:
Op het tabblad Overige instellingen :
Scripting Runtime-versie moet experimenteel zijn (NET 4.6 Equivalent). Als u dit wijzigt, moet de editor opnieuw worden opgestart.
Back-end voor scripts moet .NET zijn
API-compatibiliteitsniveau moet .NET 4.6 zijn
Schakel op het tabblad Publicatie-instellingen onder Mogelijkheden het volgende in:
InternetClient
Microfoon
Schakel verderop in het deelvenster in XR-instellingen (hieronder Publicatie-instellingen) het selectievakje Virtual Reality Ondersteund in, zorg ervoor dat de Windows Mixed Reality SDK is toegevoegd.
Terug in Build Settings Unity C# Projects wordt niet meer grijs weergegeven. Schakel het selectievakje naast dit selectievakje in.
Sluit het venster Build Settings.
Sla uw scène en project op (FILE > SAVE SCENE/ FILE > SAVE PROJECT).
Hoofdstuk 5 – Camera-instelling
Belangrijk
Als u het onderdeel Unity Set up van deze cursus wilt overslaan en direct in code wilt doorgaan, kunt u deze Azure-MR-312-Package.unitypackage downloaden, het importeren in uw project als een aangepast pakket en vervolgens doorgaan vanaf hoofdstuk 7.
Selecteer in het deelvenster Hiërarchie de hoofdcamera.
Zodra deze optie is geselecteerd, kunt u alle onderdelen van de hoofdcamera in het deelvenster Inspector zien.
- Het cameraobject moet de naam Hoofdcamera hebben (let op de spelling)
- De hoofdcamera-tag moet worden ingesteld op MainCamera (let op de spelling)
- Zorg ervoor dat de positie van de transformatie is ingesteld op 0, 0, 0
- Schakel markeringen wissen in op effen kleur.
- Stel de achtergrondkleur van het cameraonderdeel in op Zwart, Alpha 0 (Hex Code: #0000000000)
Hoofdstuk 6 – De Newtonsoft-bibliotheek importeren
Om u te helpen bij het deserialiseren en serialiseren van objecten die zijn ontvangen en verzonden naar de Bot Service, moet u de Newtonsoft-bibliotheek downloaden. U vindt hier een compatibele versie die al is georganiseerd met de juiste Unity-mapstructuur.
Als u de Newtonsoft-bibliotheek in uw project wilt importeren, gebruikt u het Unity Package dat bij deze cursus is geleverd.
Voeg de .unitypackage toe aan Unity met behulp van de menuoptie Custom Package Import Package> van assets.>
Controleer in het vak Import Unity Package dat verschijnt of alles onder (en inclusief) invoegtoepassingen is geselecteerd.
Klik op de knop Importeren om de items aan uw project toe te voegen.
Ga naar de map Newtonsoft onder Plugins in de projectweergave en selecteer de Newtonsoft-invoegtoepassing.
Als de Newtonsoft-invoegtoepassing is geselecteerd, controleert u of Any Platform is uitgeschakeld, controleert u of WSAPlayer ook is uitgeschakeld en klikt u vervolgens op Toepassen. Dit is alleen om te bevestigen dat de bestanden correct zijn geconfigureerd.
Notitie
Als u deze invoegtoepassingen markeert, worden ze alleen gebruikt in de Unity Editor. Er is een andere set van deze items in de WSA-map die wordt gebruikt nadat het project is geëxporteerd uit Unity.
Vervolgens moet u de WSA-map openen in de map Newtonsoft . U ziet een kopie van hetzelfde bestand dat u zojuist hebt geconfigureerd. Selecteer het bestand en controleer vervolgens in de inspector of
- Elk platform is uitgeschakeld
- alleen WSAPlayer is ingeschakeld
- Niet-proces is ingeschakeld
Hoofdstuk 7 : De BotTag maken
Maak een nieuw tagobject met de naam BotTag. Selecteer de hoofdcamera in de scène. Klik op de vervolgkeuzelijst Tag in het deelvenster Inspector. Klik op Tag toevoegen.
Klik op het + symbool. Geef de nieuwe tag een naam als BotTag, Opslaan.
Waarschuwing
Pas de BotTag niet toe op de hoofdcamera. Als u dit per ongeluk hebt gedaan, moet u de tag Hoofdcamera weer wijzigen in MainCamera.
Hoofdstuk 8: de klasse BotObjects maken
Het eerste script dat u moet maken, is de BotObjects-klasse, een lege klasse die is gemaakt, zodat een reeks andere klasseobjecten kan worden opgeslagen in hetzelfde script en toegankelijk is voor andere scripts in de scène.
Het maken van deze klasse is uitsluitend een architectuurkeuze. Deze objecten kunnen in plaats daarvan worden gehost in het Bot-script dat u later in deze cursus gaat maken.
Ga als volgt te werk om deze klasse te maken:
Klik met de rechtermuisknop in het deelvenster Project en klik vervolgens op Map maken>. Geef de mapscripts een naam.
Dubbelklik op de map Scripts om deze te openen. Klik vervolgens in die map met de rechtermuisknop en selecteer C#-script maken>. Noem het script BotObjects.
Dubbelklik op het nieuwe BotObjects-script om het te openen met Visual Studio.
Verwijder de inhoud van het script en vervang het door de volgende code:
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class BotObjects : MonoBehaviour{} /// <summary> /// Object received when first opening a conversation /// </summary> [Serializable] public class ConversationObject { public string ConversationId; public string token; public string expires_in; public string streamUrl; public string referenceGrammarId; } /// <summary> /// Object including all Activities /// </summary> [Serializable] public class ActivitiesRootObject { public List<Activity> activities { get; set; } public string watermark { get; set; } } [Serializable] public class Conversation { public string id { get; set; } } [Serializable] public class From { public string id { get; set; } public string name { get; set; } } [Serializable] public class Activity { public string type { get; set; } public string channelId { get; set; } public Conversation conversation { get; set; } public string id { get; set; } public From from { get; set; } public string text { get; set; } public string textFormat { get; set; } public DateTime timestamp { get; set; } public string serviceUrl { get; set; } }
Sla uw wijzigingen op in Visual Studio voordat u terugkeert naar Unity.
Hoofdstuk 9 : de klasse GazeInput maken
De volgende klasse die u gaat maken, is de klasse GazeInput . Deze klasse is verantwoordelijk voor:
- Een cursor maken die de blik van de speler vertegenwoordigt.
- Het detecteren van objecten die worden geraakt door de blik van de speler en het vasthouden van een verwijzing naar gedetecteerde objecten.
Ga als volgt te werk om deze klasse te maken:
Ga naar de map Scripts die u eerder hebt gemaakt.
Klik met de rechtermuisknop in de map, C#-script maken>. Roep het script GazeInput aan.
Dubbelklik op het nieuwe GazeInput-script om het te openen met Visual Studio.
Voeg de volgende regel rechts boven op de klassenaam in:
/// <summary> /// Class responsible for the User's gaze interactions /// </summary> [System.Serializable] public class GazeInput : MonoBehaviour
Voeg vervolgens de volgende variabelen toe in de klasse GazeInput, boven de methode Start():
[Tooltip("Used to compare whether an object is to be interacted with.")] internal string InteractibleTag = "BotTag"; /// <summary> /// Length of the gaze /// </summary> internal float GazeMaxDistance = 300; /// <summary> /// Object currently gazed /// </summary> internal GameObject FocusedObject { get; private set; } internal GameObject _oldFocusedObject { get; private set; } internal RaycastHit HitInfo { get; private set; } /// <summary> /// Cursor object visible in the scene /// </summary> internal GameObject Cursor { get; private set; } internal bool Hit { get; private set; } internal Vector3 Position { get; private set; } internal Vector3 Normal { get; private set; } private Vector3 _gazeOrigin; private Vector3 _gazeDirection;
De code voor de Methode Start() moet worden toegevoegd. Dit wordt aangeroepen wanneer de klasse wordt geïnitialiseerd:
/// <summary> /// Start method used upon initialization. /// </summary> internal virtual void Start() { FocusedObject = null; Cursor = CreateCursor(); }
Implementeer een methode waarmee de cursor van de blik wordt geïnstitueert en ingesteld:
/// <summary> /// Method to create a cursor object. /// </summary> internal GameObject CreateCursor() { GameObject newCursor = GameObject.CreatePrimitive(PrimitiveType.Sphere); newCursor.SetActive(false); // Remove the collider, so it does not block Raycast. Destroy(newCursor.GetComponent<SphereCollider>()); newCursor.transform.localScale = new Vector3(0.05f, 0.05f, 0.05f); Material mat = new Material(Shader.Find("Diffuse")); newCursor.GetComponent<MeshRenderer>().material = mat; mat.color = Color.HSVToRGB(0.0223f, 0.7922f, 1.000f); newCursor.SetActive(true); return newCursor; }
Implementeer de methoden waarmee de Raycast wordt ingesteld vanaf de hoofdcamera en houd het huidige gerichte object bij.
/// <summary> /// Called every frame /// </summary> internal virtual void Update() { _gazeOrigin = Camera.main.transform.position; _gazeDirection = Camera.main.transform.forward; UpdateRaycast(); } /// <summary> /// Reset the old focused object, stop the gaze timer, and send data if it /// is greater than one. /// </summary> private void ResetFocusedObject() { // Ensure the old focused object is not null. if (_oldFocusedObject != null) { if (_oldFocusedObject.CompareTag(InteractibleTag)) { // Provide the OnGazeExited event. _oldFocusedObject.SendMessage("OnGazeExited", SendMessageOptions.DontRequireReceiver); } } } private void UpdateRaycast() { // Set the old focused gameobject. _oldFocusedObject = FocusedObject; RaycastHit hitInfo; // Initialize Raycasting. Hit = Physics.Raycast(_gazeOrigin, _gazeDirection, out hitInfo, GazeMaxDistance); HitInfo = hitInfo; // Check whether raycast has hit. if (Hit == true) { Position = hitInfo.point; Normal = hitInfo.normal; // Check whether the hit has a collider. if (hitInfo.collider != null) { // Set the focused object with what the user just looked at. FocusedObject = hitInfo.collider.gameObject; } else { // Object looked on is not valid, set focused gameobject to null. FocusedObject = null; } } else { // No object looked upon, set focused gameobject to null. FocusedObject = null; // Provide default position for cursor. Position = _gazeOrigin + (_gazeDirection * GazeMaxDistance); // Provide a default normal. Normal = _gazeDirection; } // Lerp the cursor to the given position, which helps to stabilize the gaze. Cursor.transform.position = Vector3.Lerp(Cursor.transform.position, Position, 0.6f); // Check whether the previous focused object is this same. If so, reset the focused object. if (FocusedObject != _oldFocusedObject) { ResetFocusedObject(); if (FocusedObject != null) { if (FocusedObject.CompareTag(InteractibleTag)) { // Provide the OnGazeEntered event. FocusedObject.SendMessage("OnGazeEntered", SendMessageOptions.DontRequireReceiver); } } } }
Sla uw wijzigingen op in Visual Studio voordat u terugkeert naar Unity.
Hoofdstuk 10 – De botklasse maken
Het script dat u nu gaat maken, heet Bot. Dit is de kernklasse van uw toepassing. Hierin wordt het volgende opgeslagen:
- Referenties voor uw web-app-bot
- De methode waarmee de spraakopdrachten van de gebruiker worden verzameld
- De methode die nodig is om gesprekken met uw web-app-bot te starten
- De methode die nodig is om berichten naar uw web-app-bot te verzenden
Als u berichten naar de Bot Service wilt verzenden, bouwt de SendMessageToBot() coroutine een activiteit op. Dit is een object dat door Bot Framework wordt herkend als gegevens die door de gebruiker worden verzonden.
Ga als volgt te werk om deze klasse te maken:
Dubbelklik op de map Scripts om deze te openen.
Klik met de rechtermuisknop in de map Scripts en klik op C#-script maken>. Geef de scriptbot een naam.
Dubbelklik op het nieuwe script om het te openen met Visual Studio.
Werk de naamruimten bij zodat deze hetzelfde zijn als het volgende, boven aan de botklasse :
using Newtonsoft.Json; using System.Collections; using System.Text; using UnityEngine; using UnityEngine.Networking; using UnityEngine.Windows.Speech;
Voeg in de botklasse de volgende variabelen toe:
/// <summary> /// Static instance of this class /// </summary> public static Bot Instance; /// <summary> /// Material of the sphere representing the Bot in the scene /// </summary> internal Material botMaterial; /// <summary> /// Speech recognizer class reference, which will convert speech to text. /// </summary> private DictationRecognizer dictationRecognizer; /// <summary> /// Use this variable to identify the Bot Id /// Can be any value /// </summary> private string botId = "MRBotId"; /// <summary> /// Use this variable to identify the Bot Name /// Can be any value /// </summary> private string botName = "MRBotName"; /// <summary> /// The Bot Secret key found on the Web App Bot Service on the Azure Portal /// </summary> private string botSecret = "-- Add your Secret Key here --"; /// <summary> /// Bot Endpoint, v4 Framework uses v3 endpoint at this point in time /// </summary> private string botEndpoint = "https://directline.botframework.com/v3/directline"; /// <summary> /// The conversation object reference /// </summary> private ConversationObject conversation; /// <summary> /// Bot states to regulate the application flow /// </summary> internal enum BotState {ReadyToListen, Listening, Processing} /// <summary> /// Flag for the Bot state /// </summary> internal BotState botState; /// <summary> /// Flag for the conversation status /// </summary> internal bool conversationStarted = false;
Notitie
Zorg ervoor dat u de geheime sleutel van de bot invoegt in de botSecret-variabele. U hebt uw botgeheimsleutel aan het begin van deze cursus genoteerd in hoofdstuk 2, stap 10.
Code voor Awake() en Start() moet nu worden toegevoegd.
/// <summary> /// Called on Initialization /// </summary> void Awake() { Instance = this; } /// <summary> /// Called immediately after Awake method /// </summary> void Start() { botState = BotState.ReadyToListen; }
Voeg de twee handlers toe die worden aangeroepen door de spraakbibliotheken wanneer spraakopname begint en eindigt. De DictationRecognizer stopt automatisch met het vastleggen van de stem van de gebruiker wanneer de gebruiker stopt met spreken.
/// <summary> /// Start microphone capture. /// </summary> public void StartCapturingAudio() { botState = BotState.Listening; botMaterial.color = Color.red; // Start dictation dictationRecognizer = new DictationRecognizer(); dictationRecognizer.DictationResult += DictationRecognizer_DictationResult; dictationRecognizer.Start(); } /// <summary> /// Stop microphone capture. /// </summary> public void StopCapturingAudio() { botState = BotState.Processing; dictationRecognizer.Stop(); }
De volgende handler verzamelt het resultaat van de spraakinvoer van de gebruiker en roept de coroutine aan die verantwoordelijk is voor het verzenden van het bericht naar de Web App Bot Service.
/// <summary> /// This handler is called every time the Dictation detects a pause in the speech. /// </summary> private void DictationRecognizer_DictationResult(string text, ConfidenceLevel confidence) { // Update UI with dictation captured Debug.Log($"User just said: {text}"); // Send dictation to Bot StartCoroutine(SendMessageToBot(text, botId, botName, "message")); StopCapturingAudio(); }
De volgende coroutine wordt aangeroepen om een gesprek met de bot te starten. Zodra de gespreksoproep is voltooid, wordt de SendMessageToCoroutine() aangeroepen door een reeks parameters door te geven waarmee de activiteit wordt verzonden naar de Bot Service als een leeg bericht. Dit wordt gedaan om de Bot Service te vragen de dialoog te starten.
/// <summary> /// Request a conversation with the Bot Service /// </summary> internal IEnumerator StartConversation() { string conversationEndpoint = string.Format("{0}/conversations", botEndpoint); WWWForm webForm = new WWWForm(); using (UnityWebRequest unityWebRequest = UnityWebRequest.Post(conversationEndpoint, webForm)) { unityWebRequest.SetRequestHeader("Authorization", "Bearer " + botSecret); unityWebRequest.downloadHandler = new DownloadHandlerBuffer(); yield return unityWebRequest.SendWebRequest(); string jsonResponse = unityWebRequest.downloadHandler.text; conversation = new ConversationObject(); conversation = JsonConvert.DeserializeObject<ConversationObject>(jsonResponse); Debug.Log($"Start Conversation - Id: {conversation.ConversationId}"); conversationStarted = true; } // The following call is necessary to create and inject an activity of type //"conversationUpdate" to request a first "introduction" from the Bot Service. StartCoroutine(SendMessageToBot("", botId, botName, "conversationUpdate")); }
De volgende coroutine wordt aangeroepen om de activiteit te bouwen die naar de Bot Service moet worden verzonden.
/// <summary> /// Send the user message to the Bot Service in form of activity /// and call for a response /// </summary> private IEnumerator SendMessageToBot(string message, string fromId, string fromName, string activityType) { Debug.Log($"SendMessageCoroutine: {conversation.ConversationId}, message: {message} from Id: {fromId} from name: {fromName}"); // Create a new activity here Activity activity = new Activity(); activity.from = new From(); activity.conversation = new Conversation(); activity.from.id = fromId; activity.from.name = fromName; activity.text = message; activity.type = activityType; activity.channelId = "DirectLineChannelId"; activity.conversation.id = conversation.ConversationId; // Serialize the activity string json = JsonConvert.SerializeObject(activity); string sendActivityEndpoint = string.Format("{0}/conversations/{1}/activities", botEndpoint, conversation.ConversationId); // Send the activity to the Bot using (UnityWebRequest www = new UnityWebRequest(sendActivityEndpoint, "POST")) { www.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(json)); www.downloadHandler = new DownloadHandlerBuffer(); www.SetRequestHeader("Authorization", "Bearer " + botSecret); www.SetRequestHeader("Content-Type", "application/json"); yield return www.SendWebRequest(); // extrapolate the response Id used to keep track of the conversation string jsonResponse = www.downloadHandler.text; string cleanedJsonResponse = jsonResponse.Replace("\r\n", string.Empty); string responseConvId = cleanedJsonResponse.Substring(10, 30); // Request a response from the Bot Service StartCoroutine(GetResponseFromBot(activity)); } }
De volgende coroutine wordt aangeroepen om een antwoord aan te vragen na het verzenden van een activiteit naar de Bot Service.
/// <summary> /// Request a response from the Bot by using a previously sent activity /// </summary> private IEnumerator GetResponseFromBot(Activity activity) { string getActivityEndpoint = string.Format("{0}/conversations/{1}/activities", botEndpoint, conversation.ConversationId); using (UnityWebRequest unityWebRequest1 = UnityWebRequest.Get(getActivityEndpoint)) { unityWebRequest1.downloadHandler = new DownloadHandlerBuffer(); unityWebRequest1.SetRequestHeader("Authorization", "Bearer " + botSecret); yield return unityWebRequest1.SendWebRequest(); string jsonResponse = unityWebRequest1.downloadHandler.text; ActivitiesRootObject root = new ActivitiesRootObject(); root = JsonConvert.DeserializeObject<ActivitiesRootObject>(jsonResponse); foreach (var act in root.activities) { Debug.Log($"Bot Response: {act.text}"); SetBotResponseText(act.text); } botState = BotState.ReadyToListen; botMaterial.color = Color.blue; } }
De laatste methode die aan deze klasse moet worden toegevoegd, is vereist om het bericht weer te geven in de scène:
/// <summary> /// Set the UI Response Text of the bot /// </summary> internal void SetBotResponseText(string responseString) { SceneOrganiser.Instance.botResponseText.text = responseString; }
Notitie
Mogelijk ziet u een fout in de Unity Editor-console over het ontbreken van de klasse SceneOrganiser . Negeer dit bericht, omdat u deze klasse later in de zelfstudie gaat maken.
Sla uw wijzigingen op in Visual Studio voordat u terugkeert naar Unity.
Hoofdstuk 11 : de klasse Interacties maken
De klasse die u nu gaat maken, heet Interacties. Deze klasse wordt gebruikt om de HoloLens Tap Input van de gebruiker te detecteren.
Als de gebruiker tikt tijdens het bekijken van het Bot-object in de scène en de Bot klaar is om te luisteren naar spraakinvoer, verandert het Bot-object in rood en begint te luisteren naar spraakinvoer.
Deze klasse neemt over van de klasse GazeInput en kan dus verwijzen naar de Methode Start() en variabelen van die klasse, aangeduid met het gebruik van de basis.
Ga als volgt te werk om deze klasse te maken:
Dubbelklik op de map Scripts om deze te openen.
Klik met de rechtermuisknop in de map Scripts en klik op C#-script maken>. Geef de scriptinteracties een naam.
Dubbelklik op het nieuwe script om het te openen met Visual Studio.
Werk de naamruimten en de overname van de klasse bij zodat deze hetzelfde zijn als het volgende, boven aan de klasse Interacties :
using UnityEngine.XR.WSA.Input; public class Interactions : GazeInput {
Voeg in de klasse Interacties de volgende variabele toe:
/// <summary> /// Allows input recognition with the HoloLens /// </summary> private GestureRecognizer _gestureRecognizer;
Voeg vervolgens de Methode Start() toe:
/// <summary> /// Called on initialization, after Awake /// </summary> internal override void Start() { base.Start(); //Register the application to recognize HoloLens user inputs _gestureRecognizer = new GestureRecognizer(); _gestureRecognizer.SetRecognizableGestures(GestureSettings.Tap); _gestureRecognizer.Tapped += GestureRecognizer_Tapped; _gestureRecognizer.StartCapturingGestures(); }
Voeg de handler toe die wordt geactiveerd wanneer de gebruiker de tikbeweging voor de HoloLens-camera uitvoert
/// <summary> /// Detects the User Tap Input /// </summary> private void GestureRecognizer_Tapped(TappedEventArgs obj) { // Ensure the bot is being gazed upon. if(base.FocusedObject != null) { // If the user is tapping on Bot and the Bot is ready to listen if (base.FocusedObject.name == "Bot" && Bot.Instance.botState == Bot.BotState.ReadyToListen) { // If a conversation has not started yet, request one if(Bot.Instance.conversationStarted) { Bot.Instance.SetBotResponseText("Listening..."); Bot.Instance.StartCapturingAudio(); } else { Bot.Instance.SetBotResponseText("Requesting Conversation..."); StartCoroutine(Bot.Instance.StartConversation()); } } } }
Sla uw wijzigingen op in Visual Studio voordat u terugkeert naar Unity.
Hoofdstuk 12 – De klasse SceneOrganiser maken
De laatste klasse die in dit lab is vereist, heet SceneOrganiser. Met deze klasse wordt de scène programmatisch ingesteld door onderdelen en scripts toe te voegen aan de hoofdcamera en de juiste objecten in de scène te maken.
Ga als volgt te werk om deze klasse te maken:
Dubbelklik op de map Scripts om deze te openen.
Klik met de rechtermuisknop in de map Scripts en klik op C#-script maken>. Geef het script de naam ScèneOrganiser.
Dubbelklik op het nieuwe script om het te openen met Visual Studio.
Voeg in de klasse SceneOrganiser de volgende variabelen toe:
/// <summary> /// Static instance of this class /// </summary> public static SceneOrganiser Instance; /// <summary> /// The 3D text representing the Bot response /// </summary> internal TextMesh botResponseText;
Voeg vervolgens de methoden Awake() en Start() toe:
/// <summary> /// Called on Initialization /// </summary> private void Awake() { Instance = this; } /// <summary> /// Called immediately after Awake method /// </summary> void Start () { // Add the GazeInput class to this object gameObject.AddComponent<GazeInput>(); // Add the Interactions class to this object gameObject.AddComponent<Interactions>(); // Create the Bot in the scene CreateBotInScene(); }
Voeg de volgende methode toe, die verantwoordelijk is voor het maken van het Bot-object in de scène en het instellen van de parameters en onderdelen:
/// <summary> /// Create the Sign In button object in the scene /// and sets its properties /// </summary> private void CreateBotInScene() { GameObject botObjInScene = GameObject.CreatePrimitive(PrimitiveType.Sphere); botObjInScene.name = "Bot"; // Add the Bot class to the Bot GameObject botObjInScene.AddComponent<Bot>(); // Create the Bot UI botResponseText = CreateBotResponseText(); // Set properties of Bot GameObject Bot.Instance.botMaterial = new Material(Shader.Find("Diffuse")); botObjInScene.GetComponent<Renderer>().material = Bot.Instance.botMaterial; Bot.Instance.botMaterial.color = Color.blue; botObjInScene.transform.position = new Vector3(0f, 2f, 10f); botObjInScene.tag = "BotTag"; }
Voeg de volgende methode toe, die verantwoordelijk is voor het maken van het UI-object in de scène, die de antwoorden van de bot vertegenwoordigt:
/// <summary> /// Spawns cursor for the Main Camera /// </summary> private TextMesh CreateBotResponseText() { // Create a sphere as new cursor GameObject textObject = new GameObject(); textObject.transform.parent = Bot.Instance.transform; textObject.transform.localPosition = new Vector3(0,1,0); // Resize the new cursor textObject.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f); // Creating the text of the Label TextMesh textMesh = textObject.AddComponent<TextMesh>(); textMesh.anchor = TextAnchor.MiddleCenter; textMesh.alignment = TextAlignment.Center; textMesh.fontSize = 50; textMesh.text = "Hi there, tap on me and I will start listening."; return textMesh; }
Sla uw wijzigingen op in Visual Studio voordat u terugkeert naar Unity.
Sleep in de Unity Editor het Script SceneOrganiser van de map Scripts naar de hoofdcamera. Het onderdeel Scène-organisator moet nu worden weergegeven op het hoofdcameraobject, zoals wordt weergegeven in de onderstaande afbeelding.
Hoofdstuk 13 – Voor het gebouw
Als u een grondige test van uw toepassing wilt uitvoeren, moet u deze sideloaden op uw HoloLens. Voordat u dit doet, moet u ervoor zorgen dat:
- Alle instellingen die in hoofdstuk 4 worden genoemd, zijn correct ingesteld.
- Het script SceneOrganiser is gekoppeld aan het object Main Camera .
- Zorg ervoor dat u de geheime sleutel van de bot in de botsecret-variabele hebt ingevoegd in de botsecret-klasse.
Hoofdstuk 14: Bouwen en sideloaden naar de HoloLens
Alles wat nodig is voor de Unity-sectie van dit project is nu voltooid, dus het is tijd om het te bouwen vanuit Unity.
Navigeer naar Build-instellingen, Instellingen voor het > bouwen van bestanden....
Klik in het venster Build-instellingen op Build.
Als dat nog niet zo is, tikt u op Unity C#-projecten.
Klik op Opbouwen. Unity start een Bestandenverkenner-venster waarin u een map moet maken en vervolgens een map selecteert waarin u de app wilt inbouwen. Maak die map nu en noem deze app. Klik vervolgens met de map App geselecteerd op Map selecteren.
Unity begint met het bouwen van uw project in de app-map .
Zodra Unity klaar is met bouwen (het kan enige tijd duren), wordt er een Bestandenverkenner venster geopend op de locatie van uw build (controleer de taakbalk, omdat deze mogelijk niet altijd boven uw vensters wordt weergegeven, maar u ontvangt een melding over de toevoeging van een nieuw venster).
Hoofdstuk 15 – Implementeren in HoloLens
Implementeren op HoloLens:
U hebt het IP-adres van uw HoloLens nodig (voor Extern implementeren) en om ervoor te zorgen dat uw HoloLens zich in de ontwikkelaarsmodus bevindt. Dit doet u als volgt:
- Open de instellingen terwijl u uw HoloLens draagt.
- Ga naar Netwerk en Internet > Wi-Fi > Geavanceerde opties
- Noteer het IPv4-adres .
- Ga vervolgens terug naar Instellingen en ga vervolgens naar Update & Security > for Developers
- Stel de ontwikkelaarsmodus in.
Navigeer naar uw nieuwe Unity-build (de app-map ) en open het oplossingsbestand met Visual Studio.
Selecteer foutopsporing in de oplossingsconfiguratie.
Selecteer x86, Remote Machine in het Solution Platform.
Ga naar het menu Build en klik op Oplossing implementeren om de toepassing te sideloaden naar uw HoloLens.
Uw app moet nu worden weergegeven in de lijst met geïnstalleerde apps op uw HoloLens, klaar om te worden gestart.
Notitie
Als u wilt implementeren op een insluitende headset, stelt u het Solution Platform in op de lokale computer en stelt u de configuratie in op Foutopsporing, met x86 als platform. Implementeer vervolgens op de lokale computer met behulp van het menu Build en selecteer Oplossing implementeren.
Hoofdstuk 16 : de toepassing gebruiken op de HoloLens
Zodra u de toepassing hebt gestart, ziet u de Bot als een blauwe bol voor u.
Gebruik de tikbeweging terwijl u naar de bol kijkt om een gesprek te starten.
Wacht tot het gesprek is gestart (in de gebruikersinterface wordt een bericht weergegeven wanneer dit gebeurt). Zodra u het inleidende bericht van de bot hebt ontvangen, tikt u nogmaals op de bot, zodat deze rood wordt en begint te luisteren naar uw stem.
Zodra u stopt met praten, stuurt uw toepassing uw bericht naar de bot en ontvangt u onmiddellijk een antwoord dat wordt weergegeven in de gebruikersinterface.
Herhaal het proces om meer berichten naar uw bot te verzenden (u moet elke keer tikken wanneer u een bericht wilt verzenden).
In dit gesprek wordt gedemonstreerd hoe de bot informatie (uw naam) kan bewaren, terwijl ook bekende informatie wordt verstrekt (zoals de items die zijn opgeslagen).
Enkele vragen om de bot te stellen:
what do you sell?
how much are umbrellas?
how much are raincoats?
Uw voltooide web-app-bot (v4)
Gefeliciteerd, u hebt een mixed reality-app gebouwd die gebruikmaakt van de Azure Web App Bot, Microsoft Bot Framework v4.
Bonusoefeningen
Oefening 1
De gespreksstructuur in dit lab is zeer eenvoudig. Gebruik Microsoft LUIS om inzicht te krijgen in natuurlijke taal in uw bot.
Oefening 2
Dit voorbeeld omvat niet het beëindigen van een gesprek en het opnieuw starten van een nieuw gesprek. Als u de botfunctie wilt voltooien, probeert u de sluiting van het gesprek te implementeren.