Compare commits

...

11 Commits

234 changed files with 116682 additions and 222 deletions

View File

@ -1,20 +1,135 @@
Tree("Root") { Tree("Root") {
Composite(Race) { Composite(Sequence) {
Composite(Sequence) { BTC.InitializeSpeechManager()
// Story A: Einkaufen und Picknicken RunTree("10_SBB_Zugabteil_Szenenwahl_Selection")
BTC.GetKeyDown("Return")
BTC.Run("LoadScene.NEXT.20SBB")
}
Composite(Sequence) {
// Story B: Grotto Kochen und Essen
BTC.GetKeyDown("Backspace")
BTC.Run("LoadScene.NEXT.30SBB")
}
Composite(Sequence) {
// Story C: Wandern im Cavaglia
BTC.GetKeyDown("Tab")
BTC.Run("LoadScene.NEXT.40SBB")
}
} }
} }
Tree("10_SBB_Zugabteil_Szenenwahl_Selection") {
Composite(Sequence) {
BTC.GetKeyDown("Return")
Composite(Selector) {
Composite(Sequence) {
// Story A besucht
BTC.StoryAVisited()
Composite(Selector) {
Composite(Sequence) {
// Story A + B besucht
BTC.StoryBVisited()
Composite(Selector) {
Composite(Sequence) {
// Story A + B + C besucht
BTC.StoryCVisited()
// --- Zugabteil - Story Ende ---
// ...
BTC.GetKeyDown("Return")
}
Composite(Sequence) {
// Story A + B besucht
// Story C nicht besucht
// --- Zugabteil - Repetition Intro C ---
// ...
BTC.GetKeyDown("Return")
BTC.SetStoryCVisited()
}
}
}
Composite(Sequence) {
// Story A besucht
// Story B nicht besucht
BTC.StoryCVisited()
// Story A + C besucht
// Story B nicht besucht
// --- Zugabteil - Repetition Intro B ---
// ...
BTC.GetKeyDown("Return")
}
Composite(Sequence) {
// Story A besucht
// Story B + C nicht besucht
// --- Zugabteil - Repetition Intro BC ---
// ...
BTC.GetKeyDown("Return")
BTC.SetStoryBVisited()
}
}
}
Composite(Sequence) {
// Story A nicht besucht
BTC.StoryBVisited()
Composite(Selector) {
Composite(Sequence) {
// Story B besucht
// Story A nicht besucht
BTC.StoryCVisited()
// Story B + C besucht
// Story A nicht besucht
// --- Zugabteil - Repetition Intro A ---
// ...
BTC.GetKeyDown("Return")
}
Composite(Sequence) {
// Story B besucht
// Story A + C nicht besucht
// --- Zugabteil - Repetition Intro AC ---
// ...
BTC.GetKeyDown("Return")
}
}
}
Composite(Sequence) {
// Story A + B nicht besucht
BTC.StoryCVisited()
// Story C besucht
// Story A + B nicht besucht
// --- Zugabteil - Repetition Intro AB ---
// ...
BTC.GetKeyDown("Return")
}
Composite(Sequence) {
// Nichts besucht
BTC.GetKeyDown("Return")
Composite(Selector) {
Composite(Sequence) {
BTC.CompareRepetitionVisitedCounter(0)
// --- Zugabteil - Intro ABC erste ---
// ...
BTC.IncrementRepetitionVisitedCounter()
BTC.GetKeyDown("Return")
}
Composite(Sequence) {
// Erste Wiederholung
BTC.CompareRepetitionVisitedCounter(1)
// --- Zugabteil - Intro ABC zweite ---
// ...
BTC.IncrementRepetitionVisitedCounter()
BTC.GetKeyDown("Return")
}
Composite(Sequence) {
// Zweite Wiederholung
BTC.CompareRepetitionVisitedCounter(2)
// --- Zugabteil - Intro ABC dritte ---
// ...
BTC.GetKeyDown("Return")
}
}
}
} // First Selector
} // Sequence
}

View File

@ -1,13 +1,211 @@
Tree("Root") { Tree("Root") {
Composite(Sequence) { Composite(Sequence) {
BTC.InitializeSpeechManager()
//RunTree("32_Grotto_Kueche_Intro") //RunTree("32_Grotto_Kueche_Intro")
//RunTree("32_Grotto_Kueche_Zwiebeln_schneiden") //RunTree("32_Grotto_Kueche_Zwiebeln_schneiden")
// RunTree("32_Grotto_Kueche_alles_gefunden") //RunTree("32_Grotto_Kueche_alles_gefunden")
RunTree("32_Grotto_Kueche_Zusammen_Kochen") //RunTree("32_Grotto_Kueche_Kochen_Anzahl")
//RunTree("32_Grotto_Kueche_Zusammen_Kochen")
RunTree("32_Grotto_Story_B_Grotto")
}
}
Tree("32_Grotto_Story_B_Grotto") {
// --- Story B Grotto - Antwort Reise ---
Composite(Sequence) {
BTC.SynthesizeText("Ich möchte nirgends sonst auf der Welt leben. Möchtest du denn mit Francesca in der Küche etwas aushelfen oder wartest du im Garten auf sie?", "de-DE", "")
BTC.SpeechOutputEnded()
//BTC.SetSpeechRecognitionLanguage("it-IT")
//BTC.AddPossbileSpeechIntent("Story_B_Grotto.Nachfrage_Nonna_Grotto.2", "Laiuto in cucina.")
//BTC.AddPossbileSpeechIntent("Story_B_Grotto.Nachfrage_Nonna_Grotto.4", "Preferisco aspettarla nella sala del grotto. Non so cucinare.")
BTC.AddPossbileSpeechIntent("Story_B_Grotto.Nachfrage_Nonna_Grotto.2", "Ich helfe in der Küche.")
BTC.AddPossbileSpeechIntent("Story_B_Grotto.Nachfrage_Nonna_Grotto.4", "Ich warte im Garten auf sie.")
BTC.StartSpeechIntentRecognition()
Composite(Race) {
// -- Race 1: User sagt etwas
Composite(Sequence) {
BTC.UserStartedSpeechInput()
Composite(Selector) {
// -- Selector 1: Intent erkannt
Composite(Sequence) {
BTC.SpeechIntentRecognized()
// Intent erkannt
Composite(Race) {
Composite(Sequence) {
BTC.CompareIntentID("Story_B_Grotto.Nachfrage_Nonna_Grotto.2")
BTC.ClearPossbileSpeechIntents()
RunTree("32_Grotto_Story_B_Grotto_Antwort_Nonna_Kueche")
}
Composite(Sequence) {
BTC.CompareIntentID("Story_B_Grotto.Nachfrage_Nonna_Grotto.4")
BTC.ClearPossbileSpeechIntents()
RunTree("32_Grotto_Story_B_Grotto_Antwort_Nonna_Grotto")
}
}
}
// -- Selector 2: Intent nicht erkannt
Composite(Sequence) {
// --- Story B Grotto - Nachfrage Nonna Grotto ---
// SpeechIntentRecognized Failed: kein Intent erkannt
BTC.SynthesizeText("Was wolltest du sagen? Ich habe es nicht verstanden. Möchtest du mithelfen oder lieber im Garten warten?", "de-DE", "")
BTC.SpeechOutputEnded()
BTC.StartSpeechIntentRecognition()
// Fallback fehlt, wenn nichts gesagt wird
BTC.UserStartedSpeechInput()
BTC.SpeechIntentRecognized()
Composite(Race) {
Composite(Sequence) {
BTC.CompareIntentID("Story_B_Grotto.Nachfrage_Nonna_Grotto.2")
BTC.ClearPossbileSpeechIntents()
RunTree("32_Grotto_Story_B_Grotto_Antwort_Nonna_Kueche")
}
Composite(Sequence) {
BTC.CompareIntentID("Story_B_Grotto.Nachfrage_Nonna_Grotto.4")
BTC.ClearPossbileSpeechIntents()
RunTree("32_Grotto_Story_B_Grotto_Antwort_Nonna_Grotto")
}
}
}
// Fallback 2mal nicht verstanden: Button klick
}
}
// -- Race 2: User sagt nichts
Composite(Sequence) {
BTC.Wait(5)
BTC.CompareUserSpeechInputStarted(false)
BTC.AbortSpeechEventListener()
BTC.StopSpeechIntentRecognition()
BTC.ClearPossbileSpeechIntents()
// --- Bilder Bergell ---
//BTC.Run("LoadScene.NEXT.35Slideshow")
}
}
}
}
Tree("32_Grotto_Story_B_Grotto_Antwort_Nonna_Kueche") {
// --- Story B Grotto - Antwort Nonna Kueche ---
Composite(Sequence) {
BTC.SynthesizeText("Oh, das ist wunderbar, vielen Dank! Anschliessend seid ihr selbstverständlich zum Essen eingeladen.", "de-DE", "")
BTC.SpeechOutputEnded()
//BTC.AddPossbileSpeechIntent("Story_B_Grotto.Antwort_Nonna_Kueche.2", "Tante grazie, è molto gentile da parte Sua (o altra risposta).")
BTC.AddPossbileSpeechIntent("Story_B_Grotto.Antwort_Nonna_Kueche.2", "Vielen Dank, das ist nett (oder andere Antwort)")
BTC.StartSpeechIntentRecognition()
Composite(Race) {
// -- Race 1: User sagt etwas
Composite(Selector) {
Composite(Sequence) {
BTC.UserStartedSpeechInput()
BTC.SpeechIntentRecognized()
BTC.ClearPossbileSpeechIntents()
}
// Intent nicht erkannt
Composite(Sequence) {
BTC.ClearPossbileSpeechIntents()
}
}
// -- Race 2: User sagt nichts
Composite(Sequence) {
BTC.Wait(5)
BTC.CompareUserSpeechInputStarted(false)
BTC.StopSpeechIntentRecognition()
BTC.ClearPossbileSpeechIntents()
}
}
// --- Story B Grotto - Outro ---
// ...
}
}
Tree("32_Grotto_Story_B_Grotto_Antwort_Nonna_Grotto") {
// --- Story B Grotto - Antwort Nonna Grotto ---
Composite(Sequence) {
BTC.SynthesizeText("Okay gut, mach es dir gemütlich. Hast du etwas zum Lesen dabei?", "de-DE", "")
BTC.SpeechOutputEnded()
//BTC.AddPossbileSpeechIntent("Story_B_Grotto.Antwort_Nonna_Grotto.2", "Sì, grazie, ho qualcosa con me (o un'altra risposta)")
BTC.AddPossbileSpeechIntent("Story_B_Grotto.Antwort_Nonna_Grotto.2", "Ja, danke, ich habe etwas dabei (oder andere Antwort)")
BTC.StartSpeechIntentRecognition()
Composite(Race) {
// -- Race 1: User sagt etwas
Composite(Selector) {
Composite(Sequence) {
BTC.UserStartedSpeechInput()
BTC.SpeechIntentRecognized()
BTC.ClearPossbileSpeechIntents()
}
// Intent nicht erkannt
Composite(Sequence) {
BTC.ClearPossbileSpeechIntents()
}
}
// -- Race 2: User sagt nichts
Composite(Sequence) {
BTC.Wait(5)
BTC.CompareUserSpeechInputStarted(false)
BTC.StopSpeechIntentRecognition()
BTC.ClearPossbileSpeechIntents()
}
}
BTC.SynthesizeText("Prima, viel Spass noch und dann guten Appetit!", "de-DE", "")
BTC.SpeechOutputEnded()
//BTC.AddPossbileSpeechIntent("Story_B_Grotto.Antwort_Nonna_Grotto.6", "Grazie nonna, ciao!")
BTC.AddPossbileSpeechIntent("Story_B_Grotto.Antwort_Nonna_Grotto.6", "Danke!")
BTC.StartSpeechIntentRecognition()
Composite(Race) {
// -- Race 1: User sagt etwas
Composite(Selector) {
Composite(Sequence) {
BTC.UserStartedSpeechInput()
BTC.SpeechIntentRecognized()
BTC.ClearPossbileSpeechIntents()
//BTC.GetKeyDown("Return")
}
// Intent nicht erkannt
Composite(Sequence) {
BTC.ClearPossbileSpeechIntents()
//BTC.GetKeyDown("Return")
}
}
// -- Race 2: User sagt nichts
Composite(Sequence) {
BTC.Wait(5)
BTC.CompareUserSpeechInputStarted(false)
BTC.StopSpeechIntentRecognition()
BTC.ClearPossbileSpeechIntents()
}
}
} }
} }
Tree("32_Grotto_Kueche_Intro") { Tree("32_Grotto_Kueche_Intro") {
// --- Kueche - Intro ---
Composite(Sequence) { Composite(Sequence) {
BTC.Run("AudioSource.AUDIO.Kueche1FIntro") BTC.Run("AudioSource.AUDIO.Kueche1FIntro")
@ -15,7 +213,10 @@ Tree("32_Grotto_Kueche_Intro") {
//BTC.GetKeyDown("Return") //BTC.GetKeyDown("Return")
BTC.Run("GO/NamedGrabEvent.INTERACTABLES.Schuerze") BTC.Run("GO/NamedGrabEvent.INTERACTABLES.Schuerze")
BTC.Hide("GO/NamedGrabEvent.INTERACTABLES.Schuerze") BTC.Hide("GO/NamedGrabEvent.INTERACTABLES.Schuerze")
BTC.Run("AudioSource.AUDIO.Kueche2FIntro")
//BTC.Run("AudioSource.AUDIO.Kueche2FIntro")
BTC.SynthesizeText("Lies mir bitte das Rezept vor.", "de-DE", "")
BTC.SpeechOutputEnded()
// Rezept vorlesen: Button Klick // Rezept vorlesen: Button Klick
BTC.Set("TextMeshPro.HANDMENU.Option1Button", "text", "Rezept vorlesen") BTC.Set("TextMeshPro.HANDMENU.Option1Button", "text", "Rezept vorlesen")
@ -30,7 +231,8 @@ Tree("32_Grotto_Kueche_Intro") {
Composite(Sequence) { Composite(Sequence) {
// keine Reaktion // keine Reaktion
BTC.Wait(5) BTC.Wait(5)
// BTC.Run(Audio) BTC.SynthesizeText("Was brauchen wir? Bitte lies mir das Rezept vor.", "de-DE", "")
BTC.SpeechOutputEnded()
BTC.Run("NamedEventTrigger.HANDMENU.Option1Button") BTC.Run("NamedEventTrigger.HANDMENU.Option1Button")
} }
} }
@ -51,6 +253,7 @@ Tree("32_Grotto_Kueche_Intro") {
Composite(Sequence) { Composite(Sequence) {
// Keine Reaction // Keine Reaction
BTC.Wait(5) BTC.Wait(5)
// --- Kueche - Steinpilze Hilfe ---
BTC.Run("AudioSource.AUDIO.Kueche1FSteinpilze") BTC.Run("AudioSource.AUDIO.Kueche1FSteinpilze")
// Pilze ins Wasser Glas legen // Pilze ins Wasser Glas legen
BTC.Run("NamedGrabEvent/NamedOutline.INTERACTABLES.Steinpilze") BTC.Run("NamedGrabEvent/NamedOutline.INTERACTABLES.Steinpilze")
@ -63,6 +266,7 @@ Tree("32_Grotto_Kueche_Intro") {
} }
Tree("32_Grotto_Kueche_Zwiebeln_schneiden") { Tree("32_Grotto_Kueche_Zwiebeln_schneiden") {
// --- Kueche - Zwiebeln schneiden ---
Composite(Sequence) { Composite(Sequence) {
BTC.Run("AudioSource.AUDIO.Kueche1FZwiebelnsc") BTC.Run("AudioSource.AUDIO.Kueche1FZwiebelnsc")
@ -101,31 +305,32 @@ Tree("32_Grotto_Kueche_Zwiebeln_schneiden") {
Composite(Sequence) { Composite(Sequence) {
// Success // Success
BTC.Run("GO/NamedSocketEvent.SOCKETS.RisottoSocket") BTC.Run("GO/NamedSocketEvent.SOCKETS.RisottoSocket")
//BTC.GetKeyDown("Return")
BTC.SetBool("RisottoIsSnapped")
BTC.Disable("GO/NamedGrabEvent/NamedOutline.INTERACTABLES.Risotto") BTC.Disable("GO/NamedGrabEvent/NamedOutline.INTERACTABLES.Risotto")
BTC.SetBool("IsSnapped")
} }
Composite(Sequence) { Composite(Sequence) {
// Fail // Fail
BTC.Run("GO/NamedGrabEvent/NamedOutline.INTERACTABLES.Risotto") //BTC.GetKeyDown("Space")
BTC.ListenToEvent("GO/NamedGrabEvent/NamedOutline.INTERACTABLES.Risotto")
BTC.CompareBool("RisottoIsSnapped", false)
Composite(Marathon) { // Objekt geht zurueck
BTC.Run("AudioSource.AUDIO.Kueche2FZwiebelnsc") BTC.SetPosition("GO/NamedGrabEvent/NamedOutline.INTERACTABLES.Risotto", -6.733, 1.362, -18.908)
// Objekt geht zurueck
BTC.SetPosition("GO/NamedGrabEvent/NamedOutline.INTERACTABLES.Risotto", -6.733, 1.362, -18.908) BTC.SynthesizeText("Das hast du an den falschen Ort gestellt.", "de-DE", "")
} BTC.SpeechOutputEnded()
BTC.SetBool("RisottoIsSnapped", false)
BTC.SetBool("IsSnapped", false)
} }
} }
BTC.CompareBool("IsSnapped") BTC.CompareBool("RisottoIsSnapped")
} // Sequence } // Sequence
} }
} // Repeat } // Repeat
Composite(Sequence) { Composite(Sequence) {
BTC.Run("NamedGrabEvent/NamedOutline.INTERACTABLES.Salz") BTC.Run("NamedGrabEvent/NamedOutline.INTERACTABLES.Salz")
BTC.Disable("NamedGrabEvent/NamedOutline.INTERACTABLES.Salz") BTC.Disable("NamedGrabEvent/NamedOutline.INTERACTABLES.Salz")
BTC.Run("GO/NamedSocketEvent.SOCKETS.SalzSocket") BTC.Run("GO/NamedSocketEvent.SOCKETS.SalzSocket")
@ -156,6 +361,7 @@ Tree("32_Grotto_Kueche_Zwiebeln_schneiden") {
} }
} }
BTC.SetBool("RisottoIsSnapped", false)
BTC.Wait(1) BTC.Wait(1)
Composite(Marathon) { Composite(Marathon) {
@ -172,11 +378,15 @@ Tree("32_Grotto_Kueche_Zwiebeln_schneiden") {
Tree("32_Grotto_Kueche_alles_gefunden") { Tree("32_Grotto_Kueche_alles_gefunden") {
// --- Kueche - alles gefunden ---
Composite(Sequence) { Composite(Sequence) {
BTC.Run("AudioSource.AUDIO.Kueche2Fallesgefun") // Audio fehlt BTC.SynthesizeText("Super, du hast alles gefunden. Bitte gib nun etwas Olivenöl in den Topf.", "de-DE", "")
BTC.SpeechOutputEnded()
// Oel in Topf geben - Particle Trigger // Oel in Topf geben - Particle Trigger
// ... // ...
BTC.Run("AudioSource.AUDIO.Kueche2Fallesgefun") BTC.Run("AudioSource.AUDIO.Kueche2Fallesgefun")
//BTC.GetKeyDown("Return")
// Zwiebeln in Topf geben // Zwiebeln in Topf geben
BTC.Run("NamedGrabEvent.INTERACTABLES.Zwiebeln") BTC.Run("NamedGrabEvent.INTERACTABLES.Zwiebeln")
@ -185,49 +395,130 @@ Tree("32_Grotto_Kueche_alles_gefunden") {
BTC.Run("AudioSource.AUDIO.Kueche3Fallesgefun") BTC.Run("AudioSource.AUDIO.Kueche3Fallesgefun")
// Frage beantworten // Frage beantworten
Composite(Marathon) { BTC.AddPossbileSpeechIntent("Kueche.alles_gefunden.4", "Ja.")
BTC.Set("TextMeshPro.HANDMENU.Option1Button", "text", "Ja") BTC.AddPossbileSpeechIntent("Kueche.alles_gefunden.6", "Nein.")
BTC.Show("GO.HANDMENU.Option1Button") BTC.StartSpeechIntentRecognition()
BTC.Set("TextMeshPro.HANDMENU.Option2Button", "text", "Nein")
BTC.Show("GO.HANDMENU.Option2Button")
}
Composite(Race) { Composite(Race) {
// -- Race 1: User sagt etwas
Composite(Sequence) { Composite(Sequence) {
// Ja BTC.UserStartedSpeechInput()
BTC.Run("NamedEventTrigger.HANDMENU.Option1Button")
BTC.Hide("GO.HANDMENU.Option1Button") Composite(Selector) {
BTC.Hide("GO.HANDMENU.Option2Button") // -- Selector 1: Intent erkannt
RunTree("32_Grotto_Kueche_Interesse_Kochen") Composite(Sequence) {
BTC.SpeechIntentRecognized()
// Intent erkannt
Composite(Race) {
Composite(Sequence) {
BTC.CompareIntentID("Kueche.alles_gefunden.4")
BTC.ClearPossbileSpeechIntents()
RunTree("32_Grotto_Kueche_Interesse_Kochen")
}
Composite(Sequence) {
BTC.CompareIntentID("Kueche.alles_gefunden.6")
BTC.ClearPossbileSpeechIntents()
RunTree("32_Grotto_Kueche_Zusammen_Kochen")
}
}
}
// -- Selector 2: Intent nicht erkannt
Composite(Sequence) {
BTC.ClearPossbileSpeechIntents()
// Fallback Button
Composite(Marathon) {
BTC.Set("TextMeshPro.HANDMENU.Option1Button", "text", "Ja")
BTC.Show("GO.HANDMENU.Option1Button")
BTC.Set("TextMeshPro.HANDMENU.Option2Button", "text", "Nein")
BTC.Show("GO.HANDMENU.Option2Button")
}
Composite(Race) {
Composite(Sequence) {
// Ja
BTC.Run("NamedEventTrigger.HANDMENU.Option1Button")
BTC.AbortEventListener("NamedEventTrigger.HANDMENU.Option2Button")
BTC.Hide("GO.HANDMENU.Option1Button")
BTC.Hide("GO.HANDMENU.Option2Button")
RunTree("32_Grotto_Kueche_Interesse_Kochen")
}
Composite(Sequence) {
// Nein
BTC.Run("NamedEventTrigger.HANDMENU.Option2Button")
BTC.AbortEventListener("NamedEventTrigger.HANDMENU.Option1Button")
BTC.Hide("GO.HANDMENU.Option1Button")
BTC.Hide("GO.HANDMENU.Option2Button")
RunTree("32_Grotto_Kueche_Zusammen_Kochen")
}
}
}
}
} }
// -- Race 2: User sagt nichts
Composite(Sequence) { Composite(Sequence) {
// Nein BTC.Wait(5)
BTC.Run("NamedEventTrigger.HANDMENU.Option2Button") BTC.CompareUserSpeechInputStarted(false)
BTC.Hide("GO.HANDMENU.Option1Button") BTC.AbortSpeechEventListener()
BTC.Hide("GO.HANDMENU.Option2Button") BTC.StopSpeechIntentRecognition()
RunTree("32_Grotto_Kueche_Zusammen_Kochen") BTC.ClearPossbileSpeechIntents()
// Fallback Button
Composite(Marathon) {
BTC.Set("TextMeshPro.HANDMENU.Option1Button", "text", "Ja")
BTC.Show("GO.HANDMENU.Option1Button")
BTC.Set("TextMeshPro.HANDMENU.Option2Button", "text", "Nein")
BTC.Show("GO.HANDMENU.Option2Button")
}
Composite(Race) {
Composite(Sequence) {
// Ja
BTC.Run("NamedEventTrigger.HANDMENU.Option1Button")
BTC.AbortEventListener("NamedEventTrigger.HANDMENU.Option2Button")
BTC.Hide("GO.HANDMENU.Option1Button")
BTC.Hide("GO.HANDMENU.Option2Button")
RunTree("32_Grotto_Kueche_Interesse_Kochen")
}
Composite(Sequence) {
// Nein
BTC.Run("NamedEventTrigger.HANDMENU.Option2Button")
BTC.AbortEventListener("NamedEventTrigger.HANDMENU.Option1Button")
BTC.Hide("GO.HANDMENU.Option1Button")
BTC.Hide("GO.HANDMENU.Option2Button")
RunTree("32_Grotto_Kueche_Zusammen_Kochen")
}
}
} }
} }
} }
} }
Tree("32_Grotto_Kueche_Interesse_Kochen") { Tree("32_Grotto_Kueche_Interesse_Kochen") {
// --- Kueche - Interesse Kochen ---
Composite(Sequence) { Composite(Sequence) {
BTC.Run("AudioSource.AUDIO.Kueche1FInteresseK") BTC.Run("AudioSource.AUDIO.Kueche1FInteresseK")
BTC.Set("TextMeshPro.HANDMENU.Option1Button", "text", "Lasagne") BTC.Set("TextMeshPro.HANDMENU.Option1Button", "text", "Lasagne")
BTC.Show("GO.HANDMENU.Option1Button") BTC.Show("GO.HANDMENU.Option1Button")
BTC.SetBool("32_Grotto_Kueche_Interesse_Kochen_Button_Clicked", false)
Composite(Race) { Composite(Race) {
Composite(Sequence) { Composite(Sequence) {
// Lieblingsessen nennen // Lieblingsessen nennen
BTC.Run("NamedEventTrigger.HANDMENU.Option1Button") BTC.Run("NamedEventTrigger.HANDMENU.Option1Button")
BTC.SetBool("32_Grotto_Kueche_Interesse_Kochen_Button_Clicked")
BTC.Hide("GO.HANDMENU.Option1Button")
RunTree("32_Grotto_Kueche_Kochen_Anzahl") RunTree("32_Grotto_Kueche_Kochen_Anzahl")
} }
Composite(Sequence) { Composite(Sequence) {
// keine Antwort // keine Antwort
BTC.Wait(5) BTC.Wait(5)
BTC.CompareBool("32_Grotto_Kueche_Interesse_Kochen_Button_Clicked", false)
BTC.AbortEventListener("NamedEventTrigger.HANDMENU.Option1Button")
BTC.Hide("GO.HANDMENU.Option1Button")
RunTree("32_Grotto_Kueche_Zusammen_Kochen") RunTree("32_Grotto_Kueche_Zusammen_Kochen")
} }
} }
@ -235,44 +526,89 @@ Tree("32_Grotto_Kueche_Interesse_Kochen") {
} }
Tree("32_Grotto_Kueche_Kochen_Anzahl") { Tree("32_Grotto_Kueche_Kochen_Anzahl") {
// --- Kueche - Kochen Anzahl ---
Composite(Sequence) { Composite(Sequence) {
BTC.Run("AudioSource.AUDIO.Kueche1FKochenAnza") BTC.Run("AudioSource.AUDIO.Kueche1FKochenAnza")
// Frage beantworten // Frage beantworten
Composite(Marathon) { BTC.AddPossbileSpeechIntent("Kueche.Kochen_Anzahl.2", "sehr oft, fast täglich (oder andere Antwort)")
BTC.Set("TextMeshPro.HANDMENU.Option1Button", "text", "sehr oft") BTC.AddPossbileSpeechIntent("Kueche.Kochen_Anzahl.4", "fast nie (oder andere Antwort)")
BTC.Show("GO.HANDMENU.Option1Button") BTC.StartSpeechIntentRecognition()
BTC.Set("TextMeshPro.HANDMENU.Option2Button", "text", "selten")
BTC.Show("GO.HANDMENU.Option2Button")
}
Composite(Race) { Composite(Race) {
// -- Race 1: User sagt etwas
Composite(Sequence) { Composite(Sequence) {
// sehr oft BTC.UserStartedSpeechInput()
BTC.Run("NamedEventTrigger.HANDMENU.Option1Button")
BTC.Hide("GO.HANDMENU.Option1Button") Composite(Selector) {
BTC.Hide("GO.HANDMENU.Option2Button") // -- Selector 1: Intent erkannt
RunTree("32_Grotto_Kueche_Selbststaendig_Kochen") Composite(Sequence) {
BTC.SpeechIntentRecognized()
// Intent erkannt
Composite(Race) {
Composite(Sequence) {
BTC.CompareIntentID("Kueche.Kochen_Anzahl.2")
BTC.ClearPossbileSpeechIntents()
RunTree("32_Grotto_Kueche_Selbststaendig_Kochen")
}
Composite(Sequence) {
BTC.CompareIntentID("Kueche.Kochen_Anzahl.4")
BTC.ClearPossbileSpeechIntents()
RunTree("32_Grotto_Kueche_Zusammen_Kochen")
}
}
}
// -- Selector 2: Intent nicht erkannt
Composite(Sequence) {
BTC.ClearPossbileSpeechIntents()
// Fallback Button
Composite(Marathon) {
BTC.Set("TextMeshPro.HANDMENU.Option1Button", "text", "sehr oft")
BTC.Show("GO.HANDMENU.Option1Button")
BTC.Set("TextMeshPro.HANDMENU.Option2Button", "text", "selten")
BTC.Show("GO.HANDMENU.Option2Button")
}
Composite(Race) {
Composite(Sequence) {
// sehr oft
BTC.Run("NamedEventTrigger.HANDMENU.Option1Button")
BTC.AbortEventListener("NamedEventTrigger.HANDMENU.Option2Button")
BTC.Hide("GO.HANDMENU.Option1Button")
BTC.Hide("GO.HANDMENU.Option2Button")
RunTree("32_Grotto_Kueche_Selbststaendig_Kochen")
}
Composite(Sequence) {
// selten
BTC.Run("NamedEventTrigger.HANDMENU.Option2Button")
BTC.AbortEventListener("NamedEventTrigger.HANDMENU.Option1Button")
BTC.Hide("GO.HANDMENU.Option1Button")
BTC.Hide("GO.HANDMENU.Option2Button")
RunTree("32_Grotto_Kueche_Zusammen_Kochen")
}
}
}
}
} }
// -- Race 2: User sagt nichts
Composite(Sequence) { Composite(Sequence) {
// selten
BTC.Run("NamedEventTrigger.HANDMENU.Option2Button")
BTC.Hide("GO.HANDMENU.Option1Button")
BTC.Hide("GO.HANDMENU.Option2Button")
RunTree("32_Grotto_Kueche_Zusammen_Kochen")
}
Composite(Sequence) {
// keine Antwort
BTC.Wait(5) BTC.Wait(5)
BTC.Hide("GO.HANDMENU.Option1Button") BTC.CompareUserSpeechInputStarted(false)
BTC.Hide("GO.HANDMENU.Option2Button") BTC.AbortSpeechEventListener()
BTC.StopSpeechIntentRecognition()
BTC.ClearPossbileSpeechIntents()
RunTree("32_Grotto_Kueche_Zusammen_Kochen") RunTree("32_Grotto_Kueche_Zusammen_Kochen")
} }
} }
} }
} }
Tree("32_Grotto_Kueche_Zusammen_Kochen") { Tree("32_Grotto_Kueche_Zusammen_Kochen") {
// --- Kueche - Zusammen Kochen ---
Composite(Sequence) { Composite(Sequence) {
BTC.Run("AudioSource.AUDIO.Kueche1FZusammenKo") BTC.Run("AudioSource.AUDIO.Kueche1FZusammenKo")
@ -321,6 +657,7 @@ Tree("32_Grotto_Kueche_Zusammen_Kochen") {
} }
Tree("32_Grotto_Kueche_Selbststaendig_Kochen") { Tree("32_Grotto_Kueche_Selbststaendig_Kochen") {
// --- Kueche - Selbststaendig Kochen ---
Composite(Sequence) { Composite(Sequence) {
BTC.Run("AudioSource.AUDIO.Kueche1FSelbststae") BTC.Run("AudioSource.AUDIO.Kueche1FSelbststae")
// Selbstaendig kochen... // Selbstaendig kochen...
@ -331,17 +668,21 @@ Tree("32_Grotto_Kueche_Selbststaendig_Kochen") {
} }
Tree("32_Grotto_Kueche_Parmigiano") { Tree("32_Grotto_Kueche_Parmigiano") {
// --- Kueche - Parmigiano ---
Composite(Sequence) { Composite(Sequence) {
BTC.Run("AudioSource.AUDIO.Kueche4FZusammenKo") BTC.SynthesizeText("Schau, ich habe dir den Parmigiano hingestellt. Du kannst ihn nun in den Topf geben.", "de-DE", "")
BTC.SpeechOutputEnded()
// Parmigiano in Topf geben // Parmigiano in Topf geben
BTC.Run("NamedGrabEvent.INTERACTABLES.Parmigiano") BTC.Run("NamedGrabEvent.INTERACTABLES.Parmigiano")
BTC.Set("Collider.INTERACTABLES.Topf", "otherTag", "Parmigiano") BTC.Set("Collider.INTERACTABLES.Topf", "otherTag", "Parmigiano")
BTC.Run("Collider.INTERACTABLES.Topf") BTC.Run("Collider.INTERACTABLES.Topf")
BTC.Run("AudioSource.AUDIO.Kueche4FZusammenKo") // Richtige Audio fehlt BTC.SynthesizeText("Bist du fertig?", "de-DE", "")
BTC.SpeechOutputEnded()
// Antwort User // Antwort User
// ToDo: Sprache fehlt
BTC.Set("TextMeshPro.HANDMENU.Option1Button", "text", "Ja") BTC.Set("TextMeshPro.HANDMENU.Option1Button", "text", "Ja")
BTC.Show("GO.HANDMENU.Option1Button") BTC.Show("GO.HANDMENU.Option1Button")
Composite(Race) { Composite(Race) {
@ -350,7 +691,8 @@ Tree("32_Grotto_Kueche_Parmigiano") {
} }
BTC.Hide("GO.HANDMENU.Option1Button") BTC.Hide("GO.HANDMENU.Option1Button")
BTC.Run("AudioSource.AUDIO.Kueche4FZusammenKo") // Richtige Audio fehlt BTC.SynthesizeText("Bitte stelle den Risotto hier hin.", "de-DE", "")
BTC.SpeechOutputEnded()
// Stelle für Pfanne leuchtet // Stelle für Pfanne leuchtet
BTC.Enable("Collider/NamedOutline.INTERACTABLES.TopfUntersetzer") BTC.Enable("Collider/NamedOutline.INTERACTABLES.TopfUntersetzer")
@ -360,23 +702,57 @@ Tree("32_Grotto_Kueche_Parmigiano") {
BTC.Set("Collider/NamedOutline.INTERACTABLES.TopfUntersetzer", "otherTag", "Topf") BTC.Set("Collider/NamedOutline.INTERACTABLES.TopfUntersetzer", "otherTag", "Topf")
BTC.Run("Collider/NamedOutline.INTERACTABLES.TopfUntersetzer") BTC.Run("Collider/NamedOutline.INTERACTABLES.TopfUntersetzer")
BTC.Disable("Collider/NamedOutline.INTERACTABLES.TopfUntersetzer") BTC.Disable("Collider/NamedOutline.INTERACTABLES.TopfUntersetzer")
// ToDo: Fallback Keine Reaktion
BTC.Run("AudioSource.AUDIO.Kueche5FZusammenKo") BTC.Run("AudioSource.AUDIO.Kueche5FZusammenKo")
BTC.Run("AudioSource.AUDIO.Kueche6FZusammenKo") BTC.Run("AudioSource.AUDIO.Kueche6FZusammenKo")
// --- Outro --- // --- Kueche - Outro ---
BTC.Run("AudioSource.AUDIO.Kueche1GOutro") BTC.Run("AudioSource.AUDIO.Kueche1GOutro")
BTC.Run("AudioSource.AUDIO.Kueche2GOutro") BTC.SynthesizeText("Ich bin Giuseppe, Francescas Grossonkel. Und wer bist du?", "de-DE", "")
BTC.SpeechOutputEnded()
// Name sagen // Name sagen
BTC.Set("TextMeshPro.HANDMENU.Option1Button", "text", "Mein Name ist User.") BTC.AddPossbileSpeechIntent("Kueche.Outro.4", "Mein Name ist xy. (oder andere Antwort)")
BTC.Show("GO.HANDMENU.Option1Button") BTC.StartSpeechIntentRecognition()
Composite(Race) { Composite(Race) {
BTC.Run("NamedEventTrigger.HANDMENU.Option1Button") // -- Race 1: User sagt etwas
BTC.Wait(5) Composite(Sequence) {
} BTC.UserStartedSpeechInput()
BTC.Hide("GO.HANDMENU.Option1Button")
Composite(Selector) {
// -- Selector 1: Intent erkannt
Composite(Sequence) {
BTC.SpeechIntentRecognized()
BTC.ClearPossbileSpeechIntents()
}
// -- Selector 2: Intent nicht erkannt
Composite(Sequence) {
BTC.ClearPossbileSpeechIntents()
// Fallback Button
BTC.Set("TextMeshPro.HANDMENU.Option1Button", "text", "Mein Name ist User.")
BTC.Show("GO.HANDMENU.Option1Button")
BTC.Run("NamedEventTrigger.HANDMENU.Option1Button")
BTC.Hide("GO.HANDMENU.Option1Button")
}
}
}
// -- Race 2: User sagt nichts
Composite(Sequence) {
BTC.Wait(5)
BTC.CompareUserSpeechInputStarted(false)
BTC.AbortSpeechEventListener()
BTC.StopSpeechIntentRecognition()
BTC.ClearPossbileSpeechIntents()
}
}
BTC.Run("AudioSource.AUDIO.Kueche3GOutro") BTC.Run("AudioSource.AUDIO.Kueche3GOutro")
BTC.Run("AudioSource.AUDIO.Kueche2GOutro")
} }
} }

View File

@ -0,0 +1,135 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: 3DTree_Alnus_glutinosa_trunk_01_
m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap:
RenderType: Opaque
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BaseMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _SpecGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_Lightmaps:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_LightmapsInd:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_ShadowMasks:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats:
- _AlphaClip: 0
- _AlphaToMask: 0
- _Blend: 0
- _BlendModePreserveSpecular: 1
- _BumpScale: 1
- _ClearCoatMask: 0
- _ClearCoatSmoothness: 0
- _Cull: 2
- _Cutoff: 0.5
- _DetailAlbedoMapScale: 1
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _DstBlendAlpha: 0
- _EnvironmentReflections: 1
- _GlossMapScale: 1
- _Glossiness: 1
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _QueueOffset: 0
- _ReceiveShadows: 1
- _Smoothness: 1
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _SrcBlendAlpha: 1
- _Surface: 0
- _UVSec: 0
- _WorkflowMode: 1
- _ZWrite: 1
m_Colors:
- _BaseColor: {r: 0.5714868, g: 0.6562824, b: 0.2778465, a: 1}
- _Color: {r: 0.5714868, g: 0.6562824, b: 0.27784646, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
m_BuildTextureStacks: []
--- !u!114 &3608802487869256527
MonoBehaviour:
m_ObjectHideFlags: 11
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
m_Name:
m_EditorClassIdentifier:
version: 7

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5b8bfeb9dab014ce7bd009c822742c4e
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5407f198dec5948d38f71458cacd6568
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9e0c135ace6fa46f29244fd90f85f2eb
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d974d3b1b546248eb9b06ff0ad0e61c7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,35 @@
fileFormatVersion: 2
guid: 793d31653752c3f459437e2019654e61
labels:
- NuGetForUnity
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3c0f3f2507cd4409a9da06585b3b54e3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e2e3f2ac27eb54606b02cb9865710e80
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 164af9c74f8954fb3beac3609dcff778
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,35 @@
fileFormatVersion: 2
guid: 584bd1bb0e6303749833eec0f6b9fa42
labels:
- NuGetForUnity
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: dfa3f82205025436eb372eda0aa51e70
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: dd6f565ed58a4431294fd7d2f168cd6e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cc6e9bc6256024f658d2f978983c5e7c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,35 @@
fileFormatVersion: 2
guid: 09cdbcc422ef8a742a0f004bbb66e939
labels:
- NuGetForUnity
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

View File

@ -252,6 +252,30 @@ public class BTC : MonoBehaviour {
Task.SetSucceeded(); Task.SetSucceeded();
} }
} }
[Task]
public void AbortEventListener(string objectName)
{
List<ComponentHandler> handlers = GetHandlers(objectName);
handlers.ForEach(handler => handler.AbortEventListener(Task.getState));
if (handlers.Count == 0)
{
Debug.LogWarning($"BTC.AbortEventListener: no components under the name '{objectName}'");
Task.SetSucceeded();
}
}
[Task]
public void ListenToEvent(string objectName)
{
List<ComponentHandler> handlers = GetHandlers(objectName);
handlers.ForEach(handler => handler.ListenToEvent(Task.getState));
if (handlers.Count == 0)
{
Debug.LogWarning($"BTC.ListenToEvent: no components under the name '{objectName}'");
Task.SetSucceeded();
}
}
#endregion #endregion
#region video & sound tasks #region video & sound tasks
@ -609,8 +633,421 @@ public class BTC : MonoBehaviour {
#endif #endif
#endregion #endregion
#region Speech Intent Recognizer and Speech Synthesizer
private ViaggioAIManager _speechMng { get { return ViaggioAIManager.Instance; } }
private RequestDataModel _requestDataModel = new RequestDataModel();
private string _recognizedIntentID = "";
private bool _onIntentRecognitionSucceededEventTriggered = false;
private bool _onUserSpeechInputStartedEventTriggered = false;
private bool _onIntentRecognitionFailedEventTriggered = false;
private bool _onSpeechOutputStartedEventTriggered = false;
private bool _onSpeechOutputEndedEventTriggered = false;
private bool _abortSpeechEventListener = false;
void OnDisable()
{
UnsubscribeFromEvents();
}
private void SubscribeToEvents()
{
if (_speechMng != null)
{
// Speech Intent Recognizer Events
_speechMng.OnUserSpeechInputStartedEvent += UserSpeechInputStartedEventHandler;
_speechMng.OnIntentRecognitionSucceededEvent += IntentRecognitionSucceededEventHandler;
_speechMng.OnIntentRecognitionFailedEvent += IntentRecognitionFailedEventHandler;
// Speech Output Events
_speechMng.OnSpeechOutputStartedEvent += SpeechOutputStartedEventHandler;
_speechMng.OnSpeechOutputEndedEvent += SpeechOutputEndedEventHandler;
Debug.Log("SubscribeToEvents successfull.");
}
}
private void UnsubscribeFromEvents()
{
if (_speechMng != null)
{
_speechMng.OnIntentRecognitionSucceededEvent -= IntentRecognitionSucceededEventHandler;
_speechMng.OnUserSpeechInputStartedEvent -= UserSpeechInputStartedEventHandler;
_speechMng.OnIntentRecognitionFailedEvent -= IntentRecognitionFailedEventHandler;
_speechMng.OnSpeechOutputStartedEvent -= SpeechOutputStartedEventHandler;
_speechMng.OnSpeechOutputEndedEvent -= SpeechOutputEndedEventHandler;
}
}
private void IntentRecognitionSucceededEventHandler(object sender, string intentID)
{
_onIntentRecognitionSucceededEventTriggered = true;
_recognizedIntentID = intentID;
}
private void UserSpeechInputStartedEventHandler(object sender, object e)
{
_onUserSpeechInputStartedEventTriggered = true;
}
private void IntentRecognitionFailedEventHandler(object sender, bool e)
{
_onIntentRecognitionFailedEventTriggered = true;
}
private void SpeechOutputStartedEventHandler(object sender, bool e)
{
_onSpeechOutputStartedEventTriggered = true;
}
private void SpeechOutputEndedEventHandler(object sender, bool e)
{
_onSpeechOutputEndedEventTriggered = true;
}
[Task]
public async void InitializeSpeechManager()
{
if (Task.getState == NodeState.FirstRun)
{
while (_speechMng == null)
{
await System.Threading.Tasks.Task.Delay(10);
}
SubscribeToEvents();
Task.SetSucceeded();
return;
}
}
[Task]
public void AddPossbileSpeechIntent(string intentID, string intentText)
{
if (Task.getState == NodeState.FirstRun)
{
_requestDataModel.PossibleIntents.Add(intentID, intentText);
foreach (var r in _requestDataModel.PossibleIntents)
{
Debug.Log($"Possible Intent: {r.Key}, {r.Value}");
}
Task.SetSucceeded();
return;
}
}
[Task]
public void StartSpeechIntentRecognition()
{
if (Task.getState == NodeState.FirstRun)
{
_onUserSpeechInputStartedEventTriggered = false;
_speechMng.StartIntentRecognition(_requestDataModel.PossibleIntents);
Task.SetSucceeded();
return;
}
}
[Task]
public void UserStartedSpeechInput()
{
if (Task.getState == NodeState.FirstRun)
{
_onIntentRecognitionSucceededEventTriggered = false;
_onIntentRecognitionFailedEventTriggered = false;
}
if (_onUserSpeechInputStartedEventTriggered)
{
Task.SetSucceeded();
Debug.Log("UserStartedSpeechInput succeded.");
return;
}
if (_abortSpeechEventListener)
{
Task.SetFailed();
Debug.Log("UserStartedSpeechInput failed.");
_abortSpeechEventListener = false;
return;
}
}
[Task]
public void SpeechIntentRecognized()
{
if (_onIntentRecognitionSucceededEventTriggered)
{
Task.SetSucceeded();
Debug.Log("SpeechIntentRecognized successfull");
return;
}
if (_onIntentRecognitionFailedEventTriggered)
{
Task.SetFailed();
Debug.Log("SpeechIntentRecognized failed");
return;
}
}
[Task]
public void CompareUserSpeechInputStarted(bool value)
{
if (Task.getState == NodeState.FirstRun)
{
if (_onUserSpeechInputStartedEventTriggered == value)
{
Debug.Log($"CompareUserSpeechInputStarted with {value} = equal");
Task.SetSucceeded();
return;
}
else
{
Debug.Log($"CompareUserSpeechInputStarted with {value} = not equal");
Task.SetFailed();
return;
}
}
}
[Task]
public void CompareIntentID(string intentID)
{
if (Task.getState == NodeState.FirstRun)
{
if (_recognizedIntentID == intentID)
{
Debug.Log($"CompareIntentID {_recognizedIntentID} with {intentID} = equal");
Task.SetSucceeded();
return;
}
else
{
Debug.Log($"CompareIntentID {_recognizedIntentID} with {intentID} = not equal");
Task.SetFailed();
return;
}
}
}
[Task]
public void AbortSpeechEventListener()
{
if (Task.getState == NodeState.FirstRun)
{
_abortSpeechEventListener = true;
Task.SetSucceeded();
return;
}
}
[Task]
public void ClearPossbileSpeechIntents()
{
if (Task.getState == NodeState.FirstRun)
{
_requestDataModel.PossibleIntents.Clear();
_recognizedIntentID = "";
Task.SetSucceeded();
return;
}
}
[Task]
public void StopSpeechIntentRecognition()
{
if (Task.getState == NodeState.FirstRun)
{
_speechMng.StopIntentRecognition();
Task.SetSucceeded();
return;
}
}
[Task]
public void SetSpeechRecognitionLanguage(string languageCode)
{
if (Task.getState == NodeState.FirstRun)
{
_speechMng.SetSpeechRecognitionLanguage(languageCode);
Debug.Log($"Set Speech Recognition Language to {languageCode}");
Task.SetSucceeded();
return;
}
}
[Task]
public void SynthesizeText(string text, string languageCode, string voiceName)
{
if (Task.getState == NodeState.FirstRun)
{
_onSpeechOutputStartedEventTriggered = false;
_onSpeechOutputEndedEventTriggered = false;
if (voiceName == "")
{
// Default Voice
_speechMng.SynthesizeText(text, languageCode);
}
else
{
_speechMng.SynthesizeText(text, languageCode, voiceName);
}
}
if (_onSpeechOutputStartedEventTriggered)
{
Debug.Log("SynthesizeText: Speech Output started.");
Task.SetSucceeded();
return;
}
}
[Task]
public void SpeechOutputEnded()
{
if (_onSpeechOutputEndedEventTriggered)
{
Debug.Log("SynthesizeText: Speech Output ended.");
Task.SetSucceeded();
return;
}
}
#endregion
#region Visited Stories Manager
[Task]
public void StoryAVisited()
{
if (Task.getState == NodeState.FirstRun)
{
if (VisitedStories.StoryA)
{
Debug.Log("Story A was visited.");
Task.SetSucceeded();
return;
}
else
{
Debug.Log("Story A was not visited.");
Task.SetFailed();
return;
}
}
}
[Task]
public void StoryBVisited()
{
if (Task.getState == NodeState.FirstRun)
{
if (VisitedStories.StoryB)
{
Debug.Log("Story B was visited.");
Task.SetSucceeded();
return;
}
else
{
Debug.Log("Story B was not visited.");
Task.SetFailed();
return;
}
}
}
[Task]
public void StoryCVisited()
{
if (Task.getState == NodeState.FirstRun)
{
if (VisitedStories.StoryC)
{
Debug.Log("Story C was visited.");
Task.SetSucceeded();
return;
}
else
{
Debug.Log("Story C was not visited.");
Task.SetFailed();
return;
}
}
}
[Task]
public void SetStoryAVisited()
{
if (Task.getState == NodeState.FirstRun)
{
VisitedStories.StoryA = true;
Debug.Log($"Set Visited Story A = {VisitedStories.StoryA}");
Task.SetSucceeded();
return;
}
}
[Task]
public void SetStoryBVisited()
{
if (Task.getState == NodeState.FirstRun)
{
VisitedStories.StoryB = true;
Debug.Log($"Set Visited Story B = {VisitedStories.StoryB}");
Task.SetSucceeded();
return;
}
}
[Task]
public void SetStoryCVisited()
{
if (Task.getState == NodeState.FirstRun)
{
VisitedStories.StoryC = true;
Debug.Log($"Set Visited Story C = {VisitedStories.StoryC}");
Task.SetSucceeded();
return;
}
}
[Task]
public void IncrementRepetitionVisitedCounter()
{
if (Task.getState == NodeState.FirstRun)
{
VisitedStories.RepetitionCounter++;
Debug.Log($"Set Visited Repetition Counter = {VisitedStories.RepetitionCounter}");
Task.SetSucceeded();
return;
}
}
[Task]
public void CompareRepetitionVisitedCounter(int number)
{
if (Task.getState == NodeState.FirstRun)
{
if (VisitedStories.RepetitionCounter == number)
{
Debug.Log($"Visited Repetition Counter equals {number}");
Task.SetSucceeded();
return;
}
else
{
Debug.Log($"Visited Repetition Counter not equals {number}");
Task.SetFailed();
return;
}
}
}
#endregion
#region Oculus Input #region Oculus Input
#if OCULUSVR_AVAILABLE #if OCULUSVR_AVAILABLE
[Task] [Task]
public void OVRInputGetDown (string buttonName) { public void OVRInputGetDown (string buttonName) {
if (System.Enum.TryParse(buttonName, out OVRInput.Button button)) { if (System.Enum.TryParse(buttonName, out OVRInput.Button button)) {

View File

@ -186,7 +186,6 @@ public class ComponentHandler : MonoBehaviour {
{ {
Debug.LogWarning($"ComponentHandler.Enable: not implemented for {this.GetType()}"); Debug.LogWarning($"ComponentHandler.Enable: not implemented for {this.GetType()}");
} }
Task.SetError();
} }
public virtual void Disable(MyBT.NodeState nodeState) public virtual void Disable(MyBT.NodeState nodeState)
@ -195,7 +194,6 @@ public class ComponentHandler : MonoBehaviour {
{ {
Debug.LogWarning($"ComponentHandler.Disable: not implemented for {this.GetType()}"); Debug.LogWarning($"ComponentHandler.Disable: not implemented for {this.GetType()}");
} }
Task.SetError();
} }
public virtual void SetPosition(MyBT.NodeState nodeState, float newX, float newY, float newZ) public virtual void SetPosition(MyBT.NodeState nodeState, float newX, float newY, float newZ)
@ -204,7 +202,22 @@ public class ComponentHandler : MonoBehaviour {
{ {
Debug.LogWarning($"ComponentHandler.SetPosition: not implemented for {this.GetType()}"); Debug.LogWarning($"ComponentHandler.SetPosition: not implemented for {this.GetType()}");
} }
Task.SetError(); }
public virtual void AbortEventListener(MyBT.NodeState nodeState)
{
if (Task.isDebugging)
{
Debug.LogWarning($"ComponentHandler.AbortEventListener: not implemented for {this.GetType()}");
}
}
public virtual void ListenToEvent(MyBT.NodeState nodeState)
{
if (Task.isDebugging)
{
Debug.LogWarning($"ComponentHandler.ListenToEvent: not implemented for {this.GetType()}");
}
} }
protected float sourceAlpha; protected float sourceAlpha;

View File

@ -53,6 +53,7 @@ public class NamedEventTrigger : ComponentHandler {
EventTrigger eventTrigger; EventTrigger eventTrigger;
private bool triggered = false; private bool triggered = false;
private bool _abortEventListener = false;
public void PointerClickEventHandler () { public void PointerClickEventHandler () {
triggered = true; triggered = true;
@ -86,6 +87,25 @@ public class NamedEventTrigger : ComponentHandler {
if (triggered) { if (triggered) {
ToggleActive(false); ToggleActive(false);
Debug.Log($"NamedEventTrigger on {gameObject.name} succeded.");
Task.SetSucceeded();
return;
}
if (_abortEventListener)
{
Task.SetFailed();
Debug.Log($"NamedEventTrigger on {gameObject.name} failed.");
_abortEventListener = false;
return;
}
}
public override void AbortEventListener(MyBT.NodeState nodeState)
{
if (nodeState == NodeState.FirstRun)
{
_abortEventListener = true;
Task.SetSucceeded(); Task.SetSucceeded();
return; return;
} }

View File

@ -74,23 +74,43 @@ public class NamedGrabEvent : ComponentHandler {
if (nodeState == NodeState.FirstRun) { if (nodeState == NodeState.FirstRun) {
// reset event trigger at start // reset event trigger at start
selectEnterTriggered = false; selectEnterTriggered = false;
selectExitTriggered = false;
} }
if (nodeState == NodeState.Aborting) { if (nodeState == NodeState.Aborting) {
selectEnterTriggered = false; selectEnterTriggered = false;
selectExitTriggered = false;
} }
if (selectEnterTriggered) { if (selectEnterTriggered) {
Task.SetSucceeded(); Debug.Log($"NamedGrabEvent: Select entered event from {gameObject.name} fired.");
return;
}
if (selectExitTriggered)
{
Task.SetSucceeded(); Task.SetSucceeded();
return; return;
} }
} }
public override void ListenToEvent(MyBT.NodeState nodeState)
{
if (nodeState == NodeState.FirstRun)
{
// reset event trigger at start
selectExitTriggered = false;
Debug.Log("Enter ListenToEvent");
}
if (nodeState == NodeState.Aborting)
{
selectExitTriggered = false;
}
if (nodeState == NodeState.Running)
{
if (selectExitTriggered)
{
Debug.Log($"NamedGrabEvent: Select exited event from {gameObject.name} fired.");
Task.SetSucceeded();
return;
}
}
}
} }

View File

@ -82,6 +82,7 @@ public class NamedSocketEvent : ComponentHandler
if (triggered) if (triggered)
{ {
Debug.Log($"NamedSocketEvent: Select entered event from {gameObject.name} fired.");
Task.SetSucceeded(); Task.SetSucceeded();
return; return;
} }

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 13b91a04606704075b726fe14c9d358d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 024776a134cb948728e9177f245e275f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 52fd14c24947947008c6c2e8ac6ebe63
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,35 @@
fileFormatVersion: 2
guid: bf170c216e3c106498c37e86f177f24a
labels:
- NuGetForUnity
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: dc5bfb044d5894289bb3109b3d74198d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8949c05e0ea1c4f499339c19bb7796cc
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 28a349264b47e4e55aaf29dfc96bf7da
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,35 @@
fileFormatVersion: 2
guid: e6f53e3c23978b24d8dbdca8ead8863f
labels:
- NuGetForUnity
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d8b8ee3c0721a4d63bbe66cfde9266a2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 79657c188c41b41c1ae77c3cfdd33961
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4e965afb698e84a3684b57edda43f3d5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,35 @@
fileFormatVersion: 2
guid: d76fd1466b336fa4199b25cb4604770a
labels:
- NuGetForUnity
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f7f694d6257e843ab9484622142f5f1d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1d0e993e91bc04ca2aeb3485e2d90a67
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 75acae40c714943c5b1631d4f0e726dd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,35 @@
fileFormatVersion: 2
guid: bbd1cfe829188dc4ea7618390a5b898e
labels:
- NuGetForUnity
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 53a8e15c42c974a9bb2da52647fa5a78
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b51958ac195ee46dcb0a7733477c1f43
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ab7f345ecf665491294f4649cda621b2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,35 @@
fileFormatVersion: 2
guid: f9635e4bd591f424399120539dfb9e2d
labels:
- NuGetForUnity
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 497803f0aa7384cdba3f74f82985c23b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 81c035f68ba9948d78cfed8c8888dcb0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f60cde8978fc341ae88d154653313d53
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,35 @@
fileFormatVersion: 2
guid: 27e61e2024defba49b7788a42b0ed593
labels:
- NuGetForUnity
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

View File

@ -45,24 +45,24 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: f3657284cbc344c10b72aff76116332b, type: 3} m_Script: {fileID: 11500000, guid: f3657284cbc344c10b72aff76116332b, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
action: actionA:
m_Name: Action m_Name: Action A
m_Type: 0 m_Type: 0
m_ExpectedControlType: m_ExpectedControlType:
m_Id: c44e2df2-f504-436d-8e3e-12d803d9642e m_Id: fb157a22-9a47-466e-97a1-25ded2f3a8b8
m_Processors: m_Processors:
m_Interactions: m_Interactions:
m_SingletonActionBindings: m_SingletonActionBindings:
- m_Name: - m_Name:
m_Id: ebca9ad8-ac87-471c-8f17-f62d8084c14e m_Id: 60ed3969-99ce-484e-a6ba-c03865d49b79
m_Path: <XRController>{RightHand}/secondaryButton m_Path: <XRController>{RightHand}/{Secondary2DAxisClick}
m_Interactions: m_Interactions:
m_Processors: m_Processors:
m_Groups: m_Groups:
m_Action: Action m_Action: Action A
m_Flags: 0 m_Flags: 0
m_Flags: 0 m_Flags: 0
OnPress: OnPressA:
m_PersistentCalls: m_PersistentCalls:
m_Calls: m_Calls:
- m_Target: {fileID: 2072566747554460033} - m_Target: {fileID: 2072566747554460033}
@ -74,9 +74,45 @@ MonoBehaviour:
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0 m_IntArgument: 0
m_FloatArgument: 0 m_FloatArgument: 0
m_StringArgument: 1.0-SBB m_StringArgument:
m_BoolArgument: 0 m_BoolArgument: 0
m_CallState: 2 m_CallState: 2
actionB:
m_Name: Action B
m_Type: 0
m_ExpectedControlType:
m_Id: 6792c436-bf55-4146-aa93-e6be83aa5ed7
m_Processors:
m_Interactions:
m_SingletonActionBindings: []
m_Flags: 0
OnPressB:
m_PersistentCalls:
m_Calls: []
actionX:
m_Name: Action X
m_Type: 0
m_ExpectedControlType:
m_Id: ae0153d0-74b6-4412-80f1-4ca3572436ce
m_Processors:
m_Interactions:
m_SingletonActionBindings: []
m_Flags: 0
OnPressX:
m_PersistentCalls:
m_Calls: []
actionY:
m_Name: Action Y
m_Type: 0
m_ExpectedControlType:
m_Id: 0a8b5e05-add5-454f-a70b-1577042b74e0
m_Processors:
m_Interactions:
m_SingletonActionBindings: []
m_Flags: 0
OnPressY:
m_PersistentCalls:
m_Calls: []
--- !u!114 &2072566747554460033 --- !u!114 &2072566747554460033
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View File

@ -0,0 +1,174 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &5714472087302188827
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5021853568501081044}
- component: {fileID: 1222158309809647475}
m_Layer: 0
m_Name: SpeechControllerInputHandler
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &5021853568501081044
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5714472087302188827}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1222158309809647475
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5714472087302188827}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f3657284cbc344c10b72aff76116332b, type: 3}
m_Name:
m_EditorClassIdentifier:
actionA:
m_Name: Action A
m_Type: 0
m_ExpectedControlType:
m_Id: e977869f-e3af-44af-9a86-31776e76a0d1
m_Processors:
m_Interactions:
m_SingletonActionBindings:
- m_Name:
m_Id: 8d3a4a4e-953c-412b-840e-1f6248f6ddc3
m_Path: <XRController>{RightHand}/{PrimaryButton}
m_Interactions:
m_Processors:
m_Groups:
m_Action: Action A
m_Flags: 0
m_Flags: 0
OnPressA:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 0}
m_TargetAssemblyTypeName: ViaggioAIDemo, Assembly-CSharp
m_MethodName: StartMockIntentRecognition
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
actionB:
m_Name: Action B
m_Type: 0
m_ExpectedControlType:
m_Id: f7f49635-d0f7-4c67-bcf2-bdce6be23b9a
m_Processors:
m_Interactions:
m_SingletonActionBindings:
- m_Name:
m_Id: 37ad56d9-90f3-466b-9764-83fa5a4f6896
m_Path: <XRController>{RightHand}/{SecondaryButton}
m_Interactions:
m_Processors:
m_Groups:
m_Action: Action B
m_Flags: 0
m_Flags: 0
OnPressB:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 0}
m_TargetAssemblyTypeName: ViaggioAIDemo, Assembly-CSharp
m_MethodName: GotoNextMockIntent
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
actionX:
m_Name: Action X
m_Type: 0
m_ExpectedControlType:
m_Id: a792d5f0-00e7-42e4-9339-87923e0c6f39
m_Processors:
m_Interactions:
m_SingletonActionBindings:
- m_Name:
m_Id: a55929c1-9629-478b-9da0-e3023fb49299
m_Path: <XRController>{LeftHand}/{PrimaryButton}
m_Interactions:
m_Processors:
m_Groups:
m_Action: Action X
m_Flags: 0
m_Flags: 0
OnPressX:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 0}
m_TargetAssemblyTypeName: ViaggioAIManager, Assembly-CSharp
m_MethodName: StopIntentRecognition
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
actionY:
m_Name: Action Y
m_Type: 0
m_ExpectedControlType:
m_Id: 9053e886-15bb-49ac-993f-43f58197c97f
m_Processors:
m_Interactions:
m_SingletonActionBindings:
- m_Name:
m_Id: 943113c4-2c8b-49ec-b74d-896cfa8467d9
m_Path: <XRController>{LeftHand}/{SecondaryButton}
m_Interactions:
m_Processors:
m_Groups:
m_Action: Action Y
m_Flags: 0
m_Flags: 0
OnPressY:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 0}
m_TargetAssemblyTypeName: ViaggioAIDemo, Assembly-CSharp
m_MethodName: SynthesizeNextMockText
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 33faae782c834443b9773435cb632e69
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -596,7 +596,7 @@ GameObject:
m_Icon: {fileID: 0} m_Icon: {fileID: 0}
m_NavMeshLayer: 0 m_NavMeshLayer: 0
m_StaticEditorFlags: 0 m_StaticEditorFlags: 0
m_IsActive: 1 m_IsActive: 0
--- !u!224 &4195088450314375929 --- !u!224 &4195088450314375929
RectTransform: RectTransform:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -6487,24 +6487,24 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: f3657284cbc344c10b72aff76116332b, type: 3} m_Script: {fileID: 11500000, guid: f3657284cbc344c10b72aff76116332b, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
action: actionA:
m_Name: Action m_Name: Action A
m_Type: 0 m_Type: 0
m_ExpectedControlType: m_ExpectedControlType:
m_Id: c2b645eb-129c-4bbc-8990-954727edb910 m_Id: 77b342f4-bb75-4f94-a913-deb5f93c41b4
m_Processors: m_Processors:
m_Interactions: m_Interactions:
m_SingletonActionBindings: m_SingletonActionBindings:
- m_Name: - m_Name:
m_Id: 49408011-4cbc-493a-b23f-31a716de972e m_Id: b76f0ec6-86c7-407a-9e72-af8eb46d85f5
m_Path: <XRController>{RightHand}/primaryButton m_Path: <XRController>{LeftHand}/{Primary2DAxisClick}
m_Interactions: m_Interactions:
m_Processors: m_Processors:
m_Groups: m_Groups:
m_Action: Action m_Action: Action A
m_Flags: 0 m_Flags: 0
m_Flags: 0 m_Flags: 0
OnPress: OnPressA:
m_PersistentCalls: m_PersistentCalls:
m_Calls: m_Calls:
- m_Target: {fileID: 7978143806872874298} - m_Target: {fileID: 7978143806872874298}
@ -6519,6 +6519,42 @@ MonoBehaviour:
m_StringArgument: m_StringArgument:
m_BoolArgument: 0 m_BoolArgument: 0
m_CallState: 2 m_CallState: 2
actionB:
m_Name: Action B
m_Type: 0
m_ExpectedControlType:
m_Id: f65f10a9-265c-483f-8a7d-c2dd8bc16e21
m_Processors:
m_Interactions:
m_SingletonActionBindings: []
m_Flags: 0
OnPressB:
m_PersistentCalls:
m_Calls: []
actionX:
m_Name: Action X
m_Type: 0
m_ExpectedControlType:
m_Id: 4d844e5a-4586-4697-9b25-c9f7d2bc995f
m_Processors:
m_Interactions:
m_SingletonActionBindings: []
m_Flags: 0
OnPressX:
m_PersistentCalls:
m_Calls: []
actionY:
m_Name: Action Y
m_Type: 0
m_ExpectedControlType:
m_Id: 294c5382-b9a3-4542-b6b2-79ec2b64c2a3
m_Processors:
m_Interactions:
m_SingletonActionBindings: []
m_Flags: 0
OnPressY:
m_PersistentCalls:
m_Calls: []
--- !u!114 &7978143806872874298 --- !u!114 &7978143806872874298
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View File

@ -1 +1 @@
2024-09-05T14:35:06.9813830Z 2024-09-27T14:30:33.2362140Z

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -7,33 +7,67 @@ using UnityEngine.InputSystem;
public class OnButtonPress : MonoBehaviour public class OnButtonPress : MonoBehaviour
{ {
[Tooltip("Actions to check")] [Tooltip("Actions to check")]
public InputAction action = null; public InputAction actionA = null;
public UnityEvent OnPressA = new UnityEvent();
// When the button is pressed public InputAction actionB = null;
public UnityEvent OnPress = new UnityEvent(); public UnityEvent OnPressB = new UnityEvent();
public InputAction actionX = null;
public UnityEvent OnPressX = new UnityEvent();
public InputAction actionY = null;
public UnityEvent OnPressY = new UnityEvent();
private void Awake() private void Awake()
{ {
action.started += Pressed; actionA.started += ButtonAPressed;
actionB.started += ButtonBPressed;
actionX.started += ButtonXPressed;
actionY.started += ButtonYPressed;
} }
private void OnDestroy() private void OnDestroy()
{ {
action.started -= Pressed; actionA.started -= ButtonAPressed;
actionB.started -= ButtonBPressed;
actionX.started -= ButtonXPressed;
actionY.started -= ButtonYPressed;
} }
private void OnEnable() private void OnEnable()
{ {
action.Enable(); actionA.Enable();
actionB.Enable();
actionX.Enable();
actionY.Enable();
} }
private void OnDisable() private void OnDisable()
{ {
action.Disable(); actionA.Disable();
actionB.Disable();
actionX.Disable();
actionY.Disable();
} }
private void Pressed(InputAction.CallbackContext context) private void ButtonAPressed(InputAction.CallbackContext context)
{ {
OnPress.Invoke(); OnPressA.Invoke();
}
private void ButtonBPressed(InputAction.CallbackContext context)
{
OnPressB.Invoke();
}
private void ButtonXPressed(InputAction.CallbackContext context)
{
OnPressX.Invoke();
}
private void ButtonYPressed(InputAction.CallbackContext context)
{
OnPressY.Invoke();
} }
} }

View File

@ -0,0 +1,11 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public static class VisitedStories
{
public static bool StoryA = false;
public static bool StoryB = false;
public static bool StoryC = false;
public static int RepetitionCounter = 0;
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4d7c86be25c5e45ef9471b4667f7bc21
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 55da936e5540240e9963415c6cc1bcf2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a9d360b3e127f445aa11218b155354d2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9a6291c0c6eb24a21939fb9a8169a795
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 41084543b3a839c4885ebdef0b3457b7
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
compressionFormat: 1
quality: 1
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 1943befeb5a5d48489ea0dfe9b20a57e
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
compressionFormat: 1
quality: 1
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,23 @@
fileFormatVersion: 2
guid: 39ef44ecb6f56f14c80b432fbea228d8
AudioImporter:
externalObjects: {}
serializedVersion: 7
defaultSettings:
serializedVersion: 2
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
compressionFormat: 1
quality: 1
conversionMode: 0
preloadAudioData: 0
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
loadInBackground: 0
ambisonic: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: aea2bed9037a1456ebd94176c9c7bdc2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 6287e16ef914a5149b47dccded9a2e99
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6b1de92c860414fd19f08cfece45dc86
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f7cbb250b59df4b719dcb5318bb84f09
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,78 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Microsoft.CognitiveServices.Speech.Intent;
using UnityEngine;
public class AIServicesEvents : MonoBehaviour
{
public delegate void IntentRecognizedAction(IntentRecognitionResult intent);
public static event IntentRecognizedAction OnIntentRecognized;
public static void SendIntentRecognized(IntentRecognitionResult intent)
{
if (OnIntentRecognized != null)
OnIntentRecognized(intent);
}
public delegate void TextToAIAction(string textToSend);
public static event TextToAIAction OnTextToAI;
public static void SendTextToAI(string textToSend)
{
if (OnTextToAI != null)
OnTextToAI(textToSend);
}
public delegate void ReadTextAction(string text);
public static event ReadTextAction OnReadText;
public static void SendReadText(string text)
{
if (OnReadText != null)
OnReadText(text);
}
public delegate void StartReadAction();
public static event StartReadAction OnStartRead;
public static void SendStartRead()
{
if (OnStartRead != null)
OnStartRead();
}
public delegate void EndReadAction();
public static event EndReadAction OnEndRead;
public static void SendEndRead()
{
if (OnEndRead != null)
OnEndRead();
}
public delegate void AudioClipGeneratedAction(AudioClip clip);
public static event AudioClipGeneratedAction OnAudioClipGenerated;
public static void SendAudioClipGenerated(AudioClip clip)
{
if (OnAudioClipGenerated != null)
OnAudioClipGenerated(clip);
}
public delegate void SpeechEndedAction();
public static event SpeechEndedAction OnSpeechEnded;
public static void SendSpeechEnded()
{
if (OnSpeechEnded != null)
OnSpeechEnded();
}
public delegate void ToggleSpeechRecognitionAction(bool isOn);
public static event ToggleSpeechRecognitionAction OnToggleSpeechRecognition;
public static void SendToggleSpeechRecognition(bool isOn)
{
if (OnToggleSpeechRecognition != null)
OnToggleSpeechRecognition(isOn);
}
internal static void SendReadText(object welcomeText)
{
throw new NotImplementedException();
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5d1ce8e1d00ea45d6a830c1a4a7dd067
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,11 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[Serializable]
public struct LanguageVoice
{
public string LanguageCode;
public string VoiceName;
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d9e9caee7356299439b70e79913bdab3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,364 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Azure.AI.OpenAI.Assistants;
using Azure;
using System;
using System.Threading.Tasks;
using System.Linq;
#region Enums
public enum EOpenAIServiceState
{
StartingUp = 0,
WaitingForInstructionsReply = 10,
Ready = 20,
WaitingForReply = 30,
}
#endregion
public class OpenAIServices : MonoBehaviour
{
#region Inspector Properties
[Header("Config Values")]
[SerializeField]
private bool debugModeIsActive;
[SerializeField]
private bool ignoreReplyToStartInstructions;
[SerializeField]
private float clientInitDelay;
[SerializeField]
private float responsePollingInterval;
[SerializeField]
private string azureResourceUrl;
[SerializeField]
private string azureApiKey;
[SerializeField]
private string assistantModel;
[SerializeField]
private string assistantName;
[SerializeField]
private string assistantInstructions;
[SerializeField]
private string assistantStartInstructions;
#endregion
#region Public Properties
#region OpenAIServiceState
private EOpenAIServiceState? pendingStateToChangeToInMainThread = null;
private EOpenAIServiceState _openAIServiceState = EOpenAIServiceState.StartingUp;
public EOpenAIServiceState OpenAIServiceState
{
get { return this._openAIServiceState; }
set
{
if (value != this._openAIServiceState)
{
Debug.Log($"OpenAIServiceState changed, new value= {value}");
this._openAIServiceState = value;
this.OnOpenAIServiceStateChangedEvent?.Invoke(this, value);
}
}
}
public event EventHandler<EOpenAIServiceState> OnOpenAIServiceStateChangedEvent;
#endregion
#region LastBotReply
private string _lastBotReply = null;
public string LastBotReply
{
get { return this._lastBotReply; }
set
{
if (value != this._lastBotReply)
{
this.logIfInDebugMode($"LastBotReply changed, new value= {value}");
this._lastBotReply = value;
if (value != null)
{
this.OnLastBotReplyChangedEvent?.Invoke(this, value);
}
}
}
}
public event EventHandler<string> OnLastBotReplyChangedEvent;
#endregion
#region LastBotError
private string _lastBotError = null;
public string LastBotError
{
get { return this._lastBotError; }
set
{
if (value != this._lastBotError)
{
this.logIfInDebugMode($"LastBotError changed, new value= {value}");
this._lastBotError = value;
this.OnLastBotErrorChangedEvent?.Invoke(this, value);
}
}
}
public event EventHandler<string> OnLastBotErrorChangedEvent;
#endregion
#endregion
#region Private Properties
private AssistantsClient client;
private Assistant assistant;
private Response<ThreadRun> runResponse;
private AssistantThread thread;
private string lastMessageReceived = "";
private string lastTextReceived;
private string lastError;
private bool ignoreIncomingReplies = false;
#endregion
#region Framework Functions
void OnEnable()
{
this.init();
}
void Update()
{
this.doMainThreadTasks();
}
async void OnDisable()
{
await this.client.DeleteThreadAsync(this.thread.Id);
}
#endregion
#region Events
#endregion
#region Public Functions
public async void SendTextToBot(string textToSend)
{
this.logIfInDebugMode($"OpenAIServices SendTextToBot: {textToSend}");
this.LastBotReply = null;
this.LastBotError = null;
await this.send(textToSend);
}
public void Stop()
{
this.ignoreIncomingReplies = true;
}
#endregion
#region Private Functions
private async void init()
{
this.logIfInDebugMode("Init started");
this.OpenAIServiceState = EOpenAIServiceState.StartingUp;
this.client = new AssistantsClient(new Uri(this.azureResourceUrl), new AzureKeyCredential(this.azureApiKey));
await Task.Delay(TimeSpan.FromSeconds(this.clientInitDelay));
Response<Assistant> assistantResponse = await this.client.CreateAssistantAsync(
new AssistantCreationOptions(assistantModel)
{
Name = assistantName,
Instructions = assistantInstructions,
});
this.assistant = assistantResponse.Value;
Response<AssistantThread> threadResponse = await this.client.CreateThreadAsync();
this.thread = threadResponse.Value;
this.runResponse = await client.CreateRunAsync(
this.thread.Id,
new CreateRunOptions(assistant.Id)
{
AdditionalInstructions = assistantStartInstructions,
});
ThreadRun run = runResponse.Value;
this.logIfInDebugMode($"Init completed, ignoreReplyToStartInstructions={this.ignoreReplyToStartInstructions}");
this.ignoreIncomingReplies = this.ignoreReplyToStartInstructions;
this.OpenAIServiceState = EOpenAIServiceState.WaitingForInstructionsReply;
await this.listen();
}
private async Task send(string text)
{
this.logIfInDebugMode($"OpenAIServices Sending: {text} to Bot");
Response<ThreadMessage> messageResponse = await client.CreateMessageAsync(this.thread.Id, MessageRole.User, text);
ThreadMessage message = messageResponse.Value;
this.runResponse = await client.CreateRunAsync(this.thread.Id, new CreateRunOptions(assistant.Id));
ThreadRun run = this.runResponse.Value;
this.ignoreIncomingReplies = false;
this.logIfInDebugMode($"OpenAIServices {text} sent to Bot");
this.OpenAIServiceState = EOpenAIServiceState.WaitingForReply;
await this.listen();
}
private async Task<bool> listen()
{
Response<ThreadRun> run;
do
{
await Task.Delay(TimeSpan.FromSeconds(this.responsePollingInterval));
run = await this.client.GetRunAsync(this.thread.Id, this.runResponse.Value.Id);
}
while (Application.isPlaying && (run.Value.Status == RunStatus.Queued || run.Value.Status == RunStatus.InProgress));
if (run.Value.Status != RunStatus.Completed)
{
this.lastError = $"Status: {run.Value.Status}, Grund: {run.Value.LastError.Message}";
this.logIfInDebugMode($"Status: {run.Value.Status}, Code: {run.Value.LastError.Code}, Message: {run.Value.LastError.Message}");
return false;
}
else
{
Response<PageableList<ThreadMessage>> afterRunMessagesResponse = await client.GetMessagesAsync(this.thread.Id);
var messages = afterRunMessagesResponse.Value;
// Note: messages iterate from newest to oldest, with the messages[0] being the most recent
if (messages.FirstId != this.lastMessageReceived)
{
var threadMessage = messages.First();
foreach (MessageContent contentItem in threadMessage.ContentItems)
{
if (contentItem is MessageTextContent textItem)
{
if (this.ignoreIncomingReplies)
{
// Service has been stopped -> ignore reply
this.logIfInDebugMode($"Ignoring text reply from Bot: {textItem.Text}");
}
else
{
this.logIfInDebugMode($"Got text reply from Bot: {textItem.Text}");
this.lastTextReceived = textItem.Text;
}
}
else if (contentItem is MessageImageFileContent imageFileItem)
{
this.logIfInDebugMode($"Got image reply from Bot, FileId: {imageFileItem.FileId}");
}
}
if (this.OpenAIServiceState == EOpenAIServiceState.WaitingForInstructionsReply)
{
this.pendingStateToChangeToInMainThread = EOpenAIServiceState.Ready;
}
else if (this.OpenAIServiceState == EOpenAIServiceState.WaitingForReply)
{
this.pendingStateToChangeToInMainThread = EOpenAIServiceState.Ready;
}
this.lastMessageReceived = threadMessage.Id;
}
return true;
}
}
private void doMainThreadTasks()
{
if (this.pendingStateToChangeToInMainThread != null)
{
this.OpenAIServiceState = (EOpenAIServiceState)this.pendingStateToChangeToInMainThread;
this.pendingStateToChangeToInMainThread = null;
}
if (this.lastTextReceived != null)
{
this.LastBotReply = this.lastTextReceived;
this.lastTextReceived = null;
}
if (this.lastError != null)
{
this.LastBotError = this.lastError;
this.lastError = null;
}
}
private void logIfInDebugMode(string message)
{
if (!this.debugModeIsActive)
{
return;
}
Debug.Log($"(OpenAIServices) => {message}");
}
#endregion
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 701f2da9dc1b54cb4b6e765775a54c4c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,279 @@
using System;
using Microsoft.CognitiveServices.Speech;
using Microsoft.CognitiveServices.Speech.Audio;
using UnityEngine;
#region Enums
public enum ESpeechRecognitionState
{
StartingUp = 0,
Ready = 10,
Listening = 20,
Disabled = 90,
}
#endregion
public class SpeechRecognitionService : MonoBehaviour
{
#region Inspector Properties
[Header("Config Values")]
[SerializeField]
private bool debugModeIsActive;
[SerializeField]
private string speechKey;
[SerializeField]
private string speechRegion;
[SerializeField]
private string initialRecognitionLanguageCode; // Format: "de-CH"
#endregion
#region Public Properties
#region SpeechRecognitionState
private ESpeechRecognitionState _speechRecognitionState = ESpeechRecognitionState.StartingUp;
public ESpeechRecognitionState SpeechRecognitionState
{
get { return this._speechRecognitionState; }
set
{
if (value != this._speechRecognitionState)
{
this.logIfInDebugMode($"SpeechRecognitionState changed, new value= {value}");
this._speechRecognitionState = value;
this.OnSpeechRecognitionStateChangedEvent?.Invoke(this, value);
}
}
}
public event EventHandler<ESpeechRecognitionState> OnSpeechRecognitionStateChangedEvent;
#endregion
#endregion
#region Private Properties
private object threadLocker = new object();
private SpeechConfig speechConfig;
private bool listeningRestartIsPending;
private bool invokeUserSpeechInputStartedEventIsPending;
private string pendingPartialTranscription;
private string pendingFullTranscription;
private string invokeUserSpeechInputEndedEventIsPending;
#endregion
#region Framework Functions
void OnEnable()
{
this.initialize(this.initialRecognitionLanguageCode);
}
void Update()
{
this.doMainThreadTasks();
}
void OnDisable()
{
this.SpeechRecognitionState = ESpeechRecognitionState.Disabled;
}
#endregion
#region Private Events
private void speechRecognizer_SpeechStartDetected(object sender, RecognitionEventArgs e)
{
if (this == null || this.SpeechRecognitionState != ESpeechRecognitionState.Listening)
{
// Listener was stopped before speech start was detected
return;
}
// Set invoke pending flag (to later invoke on main thread)
this.invokeUserSpeechInputStartedEventIsPending = true;
}
private void speechRecognizer_Recognizing(object sender, SpeechRecognitionEventArgs e)
{
if (this == null || this.SpeechRecognitionState != ESpeechRecognitionState.Listening)
{
// Listener was stopped before this
return;
}
// Save pending partial transcription (to later invoke on main thread)
this.pendingPartialTranscription = e?.Result?.Text;
}
#endregion
#region Public Events
public event EventHandler<bool> OnUserSpeechInputStartedEvent;
public event EventHandler<string> OnPartialTranscriptionChangedEvent;
public event EventHandler<string> OnFullTranscriptionChangedEvent;
public event EventHandler<string> OnUserSpeechInputEndedEvent;
#endregion
#region Public Functions
public async void StartListeningOnceAsync()
{
if (this.speechConfig == null)
{
Debug.LogError("Speech recognizer is not ready yet. Wait for initialize before calling StartListeningOnceAsync");
return;
}
AudioConfig audioConfigInput = AudioConfig.FromDefaultMicrophoneInput();
using (SpeechRecognizer recognizer = new SpeechRecognizer(speechConfig))
{
lock (threadLocker)
{
this.SpeechRecognitionState = ESpeechRecognitionState.Listening;
}
recognizer.SpeechStartDetected += this.speechRecognizer_SpeechStartDetected;
recognizer.Recognizing += this.speechRecognizer_Recognizing;
SpeechRecognitionResult result = await recognizer.RecognizeOnceAsync().ConfigureAwait(false);
if (this.SpeechRecognitionState != ESpeechRecognitionState.Listening)
{
// Listener was stopped before recognition finished -> unsubscribe and return
recognizer.SpeechStartDetected -= this.speechRecognizer_SpeechStartDetected;
recognizer.Recognizing -= this.speechRecognizer_Recognizing;
return;
}
// Check result
string fullTranscription = null;
if (result.Reason == ResultReason.RecognizedSpeech && !string.IsNullOrEmpty(result.Text))
{
fullTranscription = result.Text;
this.invokeUserSpeechInputEndedEventIsPending = fullTranscription;
}
else if (result.Reason == ResultReason.NoMatch)
{
this.logIfInDebugMode("SpeechIntentService NoMatch: Speech could not be recognized.");
listeningRestartIsPending = true;
}
else if (result.Reason == ResultReason.Canceled)
{
var cancellation = CancellationDetails.FromResult(result);
this.logIfInDebugMode($"SpeechIntentService Canceled: Reason={cancellation.Reason} ErrorDetails={cancellation.ErrorDetails}");
}
lock (threadLocker)
{
this.SpeechRecognitionState = ESpeechRecognitionState.Ready;
this.pendingFullTranscription = fullTranscription;
}
recognizer.SpeechStartDetected -= this.speechRecognizer_SpeechStartDetected;
recognizer.Recognizing -= this.speechRecognizer_Recognizing;
}
}
public void StopListening()
{
this.SpeechRecognitionState = ESpeechRecognitionState.Ready;
}
public void SetRecognitionLanguage(string languageCode)
{
this.initialize(languageCode);
}
#endregion
#region Private Functions
private void initialize(string languageCode)
{
this.SpeechRecognitionState = ESpeechRecognitionState.StartingUp;
this.speechConfig = SpeechConfig.FromSubscription(this.speechKey, this.speechRegion);
this.speechConfig.SpeechRecognitionLanguage = languageCode;
// Is this hack still necessary?
var audioClip = Microphone.Start(Microphone.devices[0], true, 200, 16000);
this.logIfInDebugMode($"SpeechRecognitionService initialized using microphone: {Microphone.devices[0]}");
this.SpeechRecognitionState = ESpeechRecognitionState.Ready;
}
private void doMainThreadTasks()
{
if (this.listeningRestartIsPending)
{
this.StartListeningOnceAsync();
listeningRestartIsPending = false;
}
if (this.invokeUserSpeechInputStartedEventIsPending)
{
this.OnUserSpeechInputStartedEvent?.Invoke(this, true);
this.invokeUserSpeechInputStartedEventIsPending = false;
}
if (this.pendingPartialTranscription != null)
{
this.OnPartialTranscriptionChangedEvent?.Invoke(this, this.pendingPartialTranscription);
this.pendingPartialTranscription = null;
}
if (this.pendingFullTranscription != null)
{
this.OnFullTranscriptionChangedEvent?.Invoke(this, this.pendingFullTranscription);
this.pendingFullTranscription = null;
}
if (this.invokeUserSpeechInputEndedEventIsPending != null)
{
this.OnUserSpeechInputEndedEvent?.Invoke(this, invokeUserSpeechInputEndedEventIsPending);
this.invokeUserSpeechInputEndedEventIsPending = null;
}
}
private void logIfInDebugMode(string message)
{
if (!this.debugModeIsActive)
{
return;
}
Debug.Log($"(SpeechRecognitionService) => {message}");
}
#endregion
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2c0bfe10253cbe44aa6bdc7526969660
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,313 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CognitiveServices.Speech;
using Microsoft.CognitiveServices.Speech.Audio;
using UnityEngine;
#region Enums
public enum ESpeechSynthesizerState
{
StartingUp = 0,
Ready = 10,
Speaking = 20,
GeneratingClip = 30,
Disabled = 90,
}
public enum ESpeechOutputType
{
PlayDirectly = 0,
GenerateAudioClip = 10,
}
#endregion
public class SpeechSynthesizerService : MonoBehaviour
{
#region Inspector Properties
[Header("Config Values")]
[SerializeField]
private bool debugModeIsActive;
[SerializeField]
private ESpeechOutputType speechOutputType;
[SerializeField]
private string speechKey;
[SerializeField]
private string speechRegion;
[SerializeField]
[Tooltip("Format: 'de-CH'")]
private string initialSynthesisLanguage;
[SerializeField]
[Tooltip("Voice gallery: https://speech.microsoft.com/portal/voicegallery")]
private List<LanguageVoice> defaultSynthesisVoices;
[SerializeField]
private string fallbackMultilingualSynthesisVoiceName;
#endregion
#region Public Properties
#region SpeechSynthesizerState
private ESpeechSynthesizerState _speechSynthesizerState = ESpeechSynthesizerState.StartingUp;
public ESpeechSynthesizerState SpeechSynthesizerState
{
get { return this._speechSynthesizerState; }
set
{
if (value != this._speechSynthesizerState)
{
this.logIfInDebugMode($"SpeechSynthesizerState changed, new value= {value}");
this._speechSynthesizerState = value;
this.OnSpeechSynthesizerStateChangedEvent?.Invoke(this, value);
}
}
}
public event EventHandler<ESpeechSynthesizerState> OnSpeechSynthesizerStateChangedEvent;
#endregion
#region GeneratedAudioClip
private AudioClip _generatedAudioClip = null;
public AudioClip GeneratedAudioClip
{
get { return this._generatedAudioClip; }
set
{
if (value != this._generatedAudioClip)
{
this.logIfInDebugMode($"GeneratedAudioClip changed, new value= {value}");
this._generatedAudioClip = value;
this.OnGeneratedAudioClipChangedEvent?.Invoke(this, value);
}
}
}
public event EventHandler<AudioClip> OnGeneratedAudioClipChangedEvent;
#endregion
#endregion
#region Private Properties
private SpeechSynthesizer speechSynthesizer;
private SpeechConfig speechConfig;
private string activeLanguage = null;
private string activeVoice = null;
#endregion
#region Framework Functions
async void OnDisable()
{
Debug.Log("SpeechSynthesizerService disposing speechSynthesizer from OnDisable");
await this.disposeSynthesizer();
}
#endregion
#region Private Events
#endregion
#region Public Events
public event EventHandler<bool> OnSpeechOutputStartedEvent;
public event EventHandler<bool> OnSpeechOutputEndedEvent;
#endregion
#region Public Functions
public async void Synthesize(string text, string languageCode, string voiceNameOverride = null)
{
if (this.SpeechSynthesizerState == ESpeechSynthesizerState.Speaking)
{
await this.speechSynthesizer.StopSpeakingAsync();
}
await this.reInitializeIfNecessary(languageCode, voiceNameOverride);
if (this.speechOutputType == ESpeechOutputType.GenerateAudioClip)
{
this.SpeechSynthesizerState = ESpeechSynthesizerState.GeneratingClip;
}
else if (this.speechOutputType == ESpeechOutputType.PlayDirectly)
{
this.SpeechSynthesizerState = ESpeechSynthesizerState.Speaking;
this.OnSpeechOutputStartedEvent?.Invoke(this, true);
}
SpeechSynthesisResult synthesisResult = await this.speechSynthesizer.SpeakTextAsync(text);
if (this.speechOutputType == ESpeechOutputType.GenerateAudioClip)
{
// Todo add WavUtility
// this.GeneratedAudioClip = WavUtility.ToAudioClip(synthesisResult.AudioData);
}
else if (this.speechOutputType == ESpeechOutputType.PlayDirectly)
{
// Set state to SpeakingEnded to allow On
this.OnSpeechOutputEndedEvent?.Invoke(this, true);
}
this.SpeechSynthesizerState = ESpeechSynthesizerState.Ready;
}
#endregion
#region Private Functions
private async Task initialize(string languageCode, string voiceName)
{
this.logIfInDebugMode($"SpeechSynthesizerService initializing using language={languageCode} and voice={voiceName}");
if (this.speechSynthesizer != null)
{
Debug.Log("SpeechSynthesizerService disposing speechSynthesizer from initialize");
await this.disposeSynthesizer();
}
this.SpeechSynthesizerState = ESpeechSynthesizerState.StartingUp;
this.speechConfig = SpeechConfig.FromSubscription(this.speechKey, this.speechRegion);
this.speechConfig.SpeechSynthesisLanguage = languageCode;
this.speechConfig.SpeechSynthesisVoiceName = voiceName;
if (this.speechOutputType == ESpeechOutputType.GenerateAudioClip)
{
this.speechConfig.SetSpeechSynthesisOutputFormat(SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm);
}
AudioConfig audioConfigOutput = AudioConfig.FromDefaultSpeakerOutput();
if (this.speechOutputType == ESpeechOutputType.PlayDirectly)
{
this.speechSynthesizer = new SpeechSynthesizer(speechConfig, audioConfigOutput);
}
else if (this.speechOutputType == ESpeechOutputType.GenerateAudioClip)
{
this.speechSynthesizer = new SpeechSynthesizer(speechConfig, null);
}
this.activeLanguage = languageCode;
this.activeVoice = voiceName;
this.logIfInDebugMode($"SpeechSynthesizerService initialized using language={languageCode} and voice={voiceName}");
this.SpeechSynthesizerState = ESpeechSynthesizerState.Ready;
}
private string getDefaultVoiceForLanguage(string language)
{
string retVoiceName = this.fallbackMultilingualSynthesisVoiceName;
LanguageVoice? languageSpecificVoice = this.defaultSynthesisVoices.FirstOrDefault(lv => lv.LanguageCode == language);
if (!string.IsNullOrEmpty(languageSpecificVoice?.VoiceName))
{
retVoiceName = ((LanguageVoice)languageSpecificVoice).VoiceName;
}
return retVoiceName;
}
private async Task reInitializeIfNecessary(string languageCode, string voiceNameOverride)
{
bool reInitNecessary = false;
if (languageCode != this.activeLanguage)
{
// Language changed
reInitNecessary = true;
}
else
{
// Language unchanged
if (voiceNameOverride != null && voiceNameOverride != this.activeLanguage)
{
// Voice changed
reInitNecessary = true;
}
}
if (reInitNecessary)
{
string voiceName;
if (voiceNameOverride == null)
{
// No specific voice defined -> get default voice for this language
voiceName = this.getDefaultVoiceForLanguage(languageCode);
}
else
{
voiceName = voiceNameOverride;
}
await this.initialize(languageCode, voiceName);
}
}
private void logIfInDebugMode(string message)
{
if (!this.debugModeIsActive)
{
return;
}
Debug.Log($"(SpeechSynthesizerService) => {message}");
}
private async Task disposeSynthesizer()
{
if (this.speechSynthesizer == null)
{
return;
}
// Make sure speaking isn't active anymore, otherwise dispose will throw exception
await this.speechSynthesizer.StopSpeakingAsync();
while (this.SpeechSynthesizerState == ESpeechSynthesizerState.Speaking)
{
await Task.Delay(10);
}
this.activeLanguage = null;
this.activeVoice = null;
this.speechSynthesizer.Dispose();
this.speechSynthesizer = null;
this.SpeechSynthesizerState = ESpeechSynthesizerState.Disabled;
}
#endregion
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4d4b95d5c09d8b94f97693df0bf9a567
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 608747b8713ba4c51a3b8263220e6b4b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,326 @@
// 04.10.2021 11:00
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
public enum PivotAxis
{
Free = 10,
X = 20,
Y = 30,
Z = 40,
XY = 50,
XZ = 60,
YZ = 70,
}
public enum EEnablingBehaviour
{
Transition = 0,
Hold = 10,
Jump = 20,
}
public class ThresholdedBillboard : MonoBehaviour
{
#region Inspector Properties
[Header("Config Values")]
[Tooltip("Specifies the axis about which the object will rotate.")]
[SerializeField]
private PivotAxis pivotAxis = PivotAxis.XY;
[Tooltip("Specifies the desired OnEnable behaviour.")]
[SerializeField]
private EEnablingBehaviour enablingBehaviour;
[Tooltip("Specifies the delay in seconds before initializing.")]
[SerializeField]
private float initDelay = 0.03f;
[Tooltip("Specifies how fast the object will rotate.")]
[SerializeField]
private float rotationSpeed = 2f;
[Tooltip("Specifies the deviation at which the object will start rotating.")]
[SerializeField]
private float startBillboardingAngle = 20f;
[Tooltip("Specifies the deviation at which the object will stop rotating.")]
[SerializeField]
private float stopBillboardingAngle = 2f;
[Tooltip("Specifies if the rotation should happen after a delay.")]
[SerializeField]
private bool isDelayedModeActive = false;
[Tooltip("Only for delayed Mode: Specifies the delay before the rotation should happen.")]
[SerializeField]
private float delayedModeDelay = 0.3f;
[Header("Scene Objects")]
[Tooltip("Specifies the target we will orient to. If no target is specified, the main camera will be used.")]
[SerializeField]
private Transform targetTransform;
[Tooltip("Specifies transforms which will be set to the same rotation.")]
[SerializeField]
private List<Transform> linkedTransforms;
#endregion
#region Public Properties
public PivotAxis PivotAxis
{
get { return pivotAxis; }
set { pivotAxis = value; }
}
/// <summary>
/// The target we will orient to. If no target is specified, the main camera will be used.
/// </summary>
public Transform TargetTransform => targetTransform;
#endregion
#region Private Properties
private bool isInitialized = false;
private Camera cam;
private Quaternion rotationFrom;
private Quaternion rotationTo;
private bool delayedRotationIsPending = false;
private float lastRotationRequiredTime = 0;
#endregion
#region Framework Functions
void Awake()
{
this.cam = Camera.main;
}
void OnEnable()
{
this.initBillboardWithDelay();
}
void Update()
{
if (this.isInitialized)
{
this.rotateToTarget(false, false);
}
}
void OnDisable()
{
this.isInitialized = false;
}
#endregion
#region Events
#endregion
#region Public Functions
public void OverrideEnablingBehaviour(EEnablingBehaviour newBehaviour)
{
this.enablingBehaviour = newBehaviour;
}
public void OverrideRotationSpeed(float newRotationSpeed)
{
this.rotationSpeed = newRotationSpeed;
}
public void OverrideStartBillboardingAngle(float newStartBillboardingAngle)
{
this.startBillboardingAngle = newStartBillboardingAngle;
}
public void OverrideStopBillboardingAngle(float newStopBillboardingAngle)
{
this.stopBillboardingAngle = newStopBillboardingAngle;
}
public void JumpToDesiredRotation()
{
this.rotateToTarget(false, true);
}
#endregion
#region Private Functions
private async void initBillboardWithDelay()
{
await Task.Delay(TimeSpan.FromSeconds(this.initDelay));
if (this == null)
{
// Has been destroyed -> cancel
return;
}
this.rotationFrom = Quaternion.identity;
this.rotationTo = Quaternion.identity;
if (this.enablingBehaviour == EEnablingBehaviour.Transition)
{
this.rotateToTarget(true, false);
}
if (this.enablingBehaviour == EEnablingBehaviour.Jump)
{
this.rotateToTarget(false, true);
}
this.isInitialized = true;
}
private void rotateToTarget(bool forceRotation, bool jumpToDesiredRotation)
{
if (this.targetTransform == null)
{
this.targetTransform = this.cam.transform;
}
// Get a Vector that points from the target to the main camera.
Vector3 directionToTarget = targetTransform.position - transform.position;
bool useCameraAsUpVector = true;
// Adjust for the pivot axis.
switch (pivotAxis)
{
case PivotAxis.X:
directionToTarget.x = 0.0f;
useCameraAsUpVector = false;
break;
case PivotAxis.Y:
directionToTarget.y = 0.0f;
useCameraAsUpVector = false;
break;
case PivotAxis.Z:
directionToTarget.x = 0.0f;
directionToTarget.y = 0.0f;
break;
case PivotAxis.XY:
useCameraAsUpVector = false;
break;
case PivotAxis.XZ:
directionToTarget.x = 0.0f;
break;
case PivotAxis.YZ:
directionToTarget.y = 0.0f;
break;
case PivotAxis.Free:
default:
// No changes needed.
break;
}
// If we are right next to the camera the rotation is undefined.
if (directionToTarget.sqrMagnitude < 0.001f)
{
return;
}
Quaternion rotationCurrent = Quaternion.identity;
// Calculate and apply the rotation required to reorient the object
if (useCameraAsUpVector)
{
rotationCurrent = Quaternion.LookRotation(-directionToTarget, this.cam.transform.up);
}
else
{
rotationCurrent = Quaternion.LookRotation(-directionToTarget);
}
if (jumpToDesiredRotation)
{
this.transform.rotation = rotationCurrent;
return;
}
float deviationToDesiredRotation = Mathf.Abs(Quaternion.Angle(rotationCurrent, transform.rotation));
// Check if rotation target needs to be set
if (deviationToDesiredRotation > this.startBillboardingAngle || forceRotation)
{
if (this.isDelayedModeActive)
{
// Delayed mode
if (!this.delayedRotationIsPending)
{
// Start "timer"
this.delayedRotationIsPending = true;
this.lastRotationRequiredTime = Time.time;
}
else
{
// "Timer" running
if (Time.time > this.lastRotationRequiredTime + this.delayedModeDelay)
{
// Delaytime has passed -> start rotating
this.delayedRotationIsPending = false;
this.rotationFrom = transform.rotation;
this.rotationTo = rotationCurrent;
}
}
}
else
{
// Non delayed mode -> start rotating
this.rotationFrom = transform.rotation;
this.rotationTo = rotationCurrent;
}
}
// If delayed mode -> check if delayedRotationIsPending needs to be reset
if (deviationToDesiredRotation < this.startBillboardingAngle && this.isDelayedModeActive)
{
this.delayedRotationIsPending = false;
}
if (this.rotationTo != Quaternion.identity)
{
// Currently rotating
transform.rotation = Quaternion.Lerp(this.transform.rotation, this.rotationTo, Time.deltaTime * rotationSpeed);
for (int i = 0; i < this.linkedTransforms.Count; i++)
{
this.linkedTransforms[i].rotation = this.transform.rotation;
}
// Check if should stop
float deviationToTargetRotation = Mathf.Abs(Quaternion.Angle(this.transform.rotation, this.rotationTo));
if (deviationToTargetRotation < this.stopBillboardingAngle)
{
this.rotationFrom = Quaternion.identity;
this.rotationTo = Quaternion.identity;
}
}
}
#endregion
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c22b44c57fc34aa4e92dd02ee1b3d593
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,247 @@
// 04.10.2021 11:00
using System;
using System.Threading.Tasks;
using UnityEngine;
public class ThresholdedPositioner : MonoBehaviour
{
#region Inspector Properties
[Header("Config Values")]
[Tooltip("Sets the desired position relative to target.")]
[SerializeField]
private Vector3 offsetToTarget;
[Tooltip("Should the position be fixed on height of the camera?")]
[SerializeField]
private bool keepOnCamHeight;
[Tooltip("Specifies the desired OnEnable behaviour.")]
[SerializeField]
private EEnablingBehaviour enablingBehaviour = EEnablingBehaviour.Transition;
[Tooltip("Specifies the delay in seconds before initializing.")]
[SerializeField]
private float initDelay = 0.03f;
[Tooltip("Specifies how fast the object will move.")]
[SerializeField]
private float movingSpeed = 4f;
[Tooltip("Distance from desiredPos which will start movement.")]
[SerializeField]
private float startMovingDistance = 0.2f;
[Tooltip("Distance to desiredPos which will stop movement.")]
[SerializeField]
private float stopMovingDistance = 0.02f;
[Tooltip("If keepAwayFromTransform is set: Minimal distance to keepAwayFromTransform.")]
[SerializeField]
private float keepAwayDistance = 0.5f;
[Header("Scene Objects")]
[Tooltip("Uses camera if not set")]
[SerializeField]
private Transform target;
[Tooltip("Stays away from this transform")]
[SerializeField]
private Transform keepAwayTransform;
#endregion
#region Public Properties
#endregion
#region Private Properties
private Camera cam;
private bool isInitialized = false;
private bool isMoving = false;
#endregion
#region Framework Functions
void Awake()
{
this.cam = Camera.main;
}
void OnEnable()
{
this.initPositionerWithDelay();
}
void Update()
{
if (this.isInitialized)
{
this.updateIsMoving();
if (this.isMoving)
{
this.updatePosition();
}
if (this.keepAwayTransform != null)
{
this.ensureMinDistanceToKeepAwayTransform();
}
}
}
void OnDisable()
{
this.isInitialized = false;
}
#endregion
#region Events
#endregion
#region Public Functions
public void OverrideEnablingBehaviour(EEnablingBehaviour newBehaviour)
{
this.enablingBehaviour = newBehaviour;
}
public void OverrideStartMovingDistance(float newStartMovingDistance)
{
this.startMovingDistance = newStartMovingDistance;
}
public void OverrideStopMovingDistance(float newStopMovingDistance)
{
this.stopMovingDistance = newStopMovingDistance;
}
public void OverrideMovingSpeed(float newMovingSpeed)
{
this.movingSpeed = newMovingSpeed;
}
public void OverrideKeepAwayFromTransform(Transform _keepAwayTransform, float _keepAwayDistance)
{
this.keepAwayTransform = _keepAwayTransform;
this.keepAwayDistance = _keepAwayDistance;
}
public void JumpToDesiredPosition()
{
this.transform.position = this.getDesiredPosition();
}
#endregion
#region Private Functions
private async void initPositionerWithDelay()
{
await Task.Delay(TimeSpan.FromSeconds(this.initDelay));
if (this.enablingBehaviour == EEnablingBehaviour.Transition)
{
this.isMoving = true;
}
if (this.enablingBehaviour == EEnablingBehaviour.Hold)
{
this.isMoving = false;
}
if (this.enablingBehaviour == EEnablingBehaviour.Jump)
{
this.transform.position = this.getDesiredPosition();
}
this.isInitialized = true;
}
private Vector3 getDesiredPosition()
{
// Ensure that we always have a target (in case this gets called before init)
if (this.target == null)
{
this.target = this.cam.transform;
}
Vector3 desiredPos = this.target.position
+ this.target.right * this.offsetToTarget.x
+ this.target.up * this.offsetToTarget.y
+ this.target.forward * this.offsetToTarget.z;
if (this.keepOnCamHeight)
{
// Override y position to keep on Cam height
desiredPos.y = this.cam.transform.position.y;
// Check if distance is still sufficient after overriding y pos
float distance = Vector3.Distance(desiredPos, this.target.position);
if (distance < this.offsetToTarget.z)
{
desiredPos = (desiredPos - this.target.position).normalized * this.offsetToTarget.z + this.target.position;
//Vector3 newPos = (this.transform.position - this.keepAwayTransform.position).normalized * this.keepAwayDistance + this.keepAwayTransform.position;
}
}
return desiredPos;
}
private void updateIsMoving()
{
float distance = Vector3.Distance(this.transform.position, this.getDesiredPosition());
if (this.isMoving && distance < this.stopMovingDistance)
{
this.isMoving = false;
}
else if (!this.isMoving && distance > this.startMovingDistance)
{
this.isMoving = true;
}
}
private void updatePosition()
{
Vector3 newPosition = Vector3.Lerp(this.transform.position, this.getDesiredPosition(), this.movingSpeed * Time.deltaTime);
if (this.keepAwayTransform != null)
{
float distance = Vector3.Distance(newPosition, this.keepAwayTransform.position);
if (distance < this.keepAwayDistance)
{
// Getting too close to keep away from transform -> don't move
newPosition = this.transform.position;
}
}
this.transform.position = newPosition;
}
private void ensureMinDistanceToKeepAwayTransform()
{
float distance = Vector3.Distance(this.transform.position, this.keepAwayTransform.position);
if (distance < this.keepAwayDistance)
{
Vector3 newPos = (this.transform.position - this.keepAwayTransform.position).normalized * this.keepAwayDistance + this.keepAwayTransform.position;
this.transform.position = newPos;
}
}
#endregion
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c2b06c81ea998c644afbfc1824d33063
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,54 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UnityDevSetLocalPosition : MonoBehaviour
{
#region Inspector Properties
[Header("Config Values")]
[SerializeField]
private Vector3 unityDevLocalPosition;
#endregion
#region Public Properties
#endregion
#region Private Properties
#endregion
#region Framework Functions
void Awake()
{
this.setLocalPosition();
}
#endregion
#region Events
#endregion
#region Public Functions
#endregion
#region Private Functions
private void setLocalPosition()
{
if (Application.isEditor)
{
this.transform.localPosition = this.unityDevLocalPosition;
}
}
#endregion
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7a15a52aeb2f21846aab8be72e6b241a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,75 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
[Serializable]
public struct KeyPressAction
{
[SerializeField]
private KeyCode keyCode;
[SerializeField]
private UnityEvent action;
public KeyCode KeyCode => keyCode;
public UnityEvent Action => action;
}
public class UnityKeyPressHandler : MonoBehaviour
{
#region Inspector Properties
[Header("Config Values")]
[SerializeField]
private List<KeyPressAction> keyPressActions;
#endregion
#region Public Properties
#endregion
#region Private Properties
#endregion
#region Framework Functions
void Update()
{
if (Application.isEditor)
{
this.checkForUnityKeyPress();
}
}
#endregion
#region Events
#endregion
#region Public Functions
#endregion
#region Private Functions
private void checkForUnityKeyPress()
{
foreach (KeyPressAction action in this.keyPressActions)
{
if (Input.GetKeyDown(action.KeyCode))
{
action.Action.Invoke();
}
}
}
#endregion
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 03653c241b7024e4382eb20b30c81999
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b1ef4b88f24a0ee45813c850ccf1bfed
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 49398d1599ab7e54da7ef0d91f669e22
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 59df6f89bfc4d5e419bacff56431fea2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More