Skip to main content

Goals Showcase

This room showcases various ways in which Goals can be utilized to create a variety of unique and interactive experiences with Inworld characters in Unity.

Playground Goals Showcase

Parameters

The Parameters showcase is an example of how trigger parameters can be utilized to inject realtime information from the Unity client to an Inworld character action at runtime.

Parameters Showcase

In this case the client sends a phrase input by the player in the Unity Playground as a trigger parameter to the Rhyme Bot.

public void SendTrigger()
{
m_InworldCharacter.SendTrigger("rhyme", true, new Dictionary<string, string>()
{
{"phrase", m_InputField.text}
});
}

This will activate the "rhyme" goal and trigger the "make a rhyme with {{p.phrase}}" instruction.

goals:
- name: "rhyme"
repeatable: True
activation:
trigger: "rhyme"
actions:
- instruction: "make a rhyme with {{p.phrase}}"

This will cause the Rhyme Bot to make up a rhyme with the given phrase. For example, if you input the phrase "apples" Rhyme Bot will come up with a rhyme about apples:

Parameters Showcase Input Apples

For more information on utilizing Parameters see Customizable parameters changing action in runtime.

Enable Goals with Intents

The Enable Goals with Intents showcase is multi-feature example showing how goals can be enabled/disabled with Intents by using Character Mutations.

Enable Goals with Intents Showcase

The demo requires that you first say 'hello' to Goals Bot, this will activate the greeting intent which will enable the left and right goals.

intents:
- name: "greeting"
training_phrases:
- "Hello"
- "Hi"
- "Hey"
- "Hi there"
- "Greetings"
- "Howdy"
- "Hey there"
- "Hiya"
- "Sup"

goals:
- name: "greeting"
activation:
intent: "greeting"
actions:
- instruction: "greet {player} and ask if they would like you to walk left or right."
character_changes:
enable_goals:
- "left"
- "right"
disable_goals:
- "left_disabled"
- "right_disabled"

From here you can instruct Goals Bot to walk left or right utilizing the left and right intents.

intents:
- name: "left"
training_phrases:
- "left"
- "walk left"
- "go left"
- "head left"

- name: "right"
training_phrases:
- "right"
- "walk right"
- "go right"
- "head right"

goals:
- name: "left"
enabled_by_default: false
repeatable: true
activation:
intent: "left"
actions:
- say_verbatim: "I will head left."
character_changes:
enable_goals:
- "right"
- "left_disabled"
disable_goals:
- "left"
- "right_disabled"

- name: "right"
enabled_by_default: false
repeatable: true
activation:
intent: "right"
actions:
- say_verbatim: "I will head right."
character_changes:
enable_goals:
- "left"
- "right_disabled"
disable_goals:
- "right"
- "left_disabled"

- name: "left_disabled"
enabled_by_default: true
repeatable: true
activation:
intent: "left"
actions:
- say_verbatim: "I'm sorry I can't walk left."

- name: "right_disabled"
enabled_by_default: true
repeatable: true
activation:
intent: "right"
actions:
- say_verbatim: "I'm sorry I can't walk right."

Asking Goals Bot to walk right will activate the corresponding goal, which in turn will disable the right goal and enable the left goal. The Goals Bot will then walk toward the right.

Enable Goals with Intents Walking

Similarly asking Goals Bot to walk left will disable the left goal and enable the right goal.

For more information on utilizing intent recognition for activating goals see the Activation section of Concept Definitions. For more information on enabling and disabling goals and other character mutations checkout Character Mutations.

Data Retrieval

The Data Retrieval showcase is a multi-feature example of utilizing Intents, Entities and Parameters to have an Inworld character dynamically fetch and relay data requested by the player.

In this case, our character Data Retrieval Bot provides population data for either New York City or San Francisco.

Data Retrieval Showcase

This works first by utilizing Intents and Entities to interpret a players request. Data Retrieval Bot listens for the player to ask what the population is in a particular city. This will activate the get_population_goal goal which will return any matching city entity to the client as a trigger parameter.

intents:
- name: "population_in_city"
training_phrases:
- "What's the population of "
- "What is the population of "
- "population in"
- "population of"

entities:
- name: "city"
map_entries:
- value: "san_francisco"
display_name: "San Francisco"
synonyms:
- "sf"
- "san francisco"
- value: "new_york"
display_name: "New York City"
synonyms:
- "nyc"
- "new york"
- "new york city"

goals:
- name: "get_population_goal"
repeatable: true
activation:
intent: "population_in_city"
actions:
- send_trigger: "get_population"
trigger_params: [city]

On the client side we have a listener for these triggers sent by the server. When a trigger is received by the client, we first check for the city parameter which indicates if the player asked for the population of a supported city.

void OnDataRetrievalBotServerTrigger(string triggerName, Dictionary<string, string> parameters) 
{
switch (triggerName)
{
case "get_population":
if (!parameters.TryGetValue("city", out var city) || string.IsNullOrEmpty(city))
{
InworldController.Instance.SendTrigger("unsupported_city", m_InworldPlaygroundCharacter.ID, new Dictionary<string, string>
{
{ "city", city }
});
break;
}
GetPopulation(city);
break;
}
}

If the city parameter does exist (and is not null) we can attempt to fetch the data on the client. In this case we are fetching the data from a JSON file.

{
"Cities": [
{
"Name": "San Francisco",
"Population": "808437",
"Year": "2022"
},
{
"Name": "New York City",
"Population": "8335897",
"Year": "2022"
}
],
"Source": "https://www2.census.gov/programs-surveys/popest/tables/2020-2022/cities/totals/"
}
void GetPopulation(string cityName)
{
Debug.Log("Getting population data for: " + cityName);
try
{
TextAsset populationDataTextAsset = Resources.Load<TextAsset>("PopulationData");
var populationData = JsonUtility.FromJson<PopulationData>(populationDataTextAsset.text);

foreach (City city in populationData.Cities)
{
if (city.Name == cityName)
{
GivePopulationInfo(cityName, city.Population.ToString());
break;
}
}
}
catch (Exception e)
{
Debug.LogWarning($"Failed to get population data for: {cityName}, error: {e}");
}
}

If the data is successfully fetched, we can then relay that information to Data Retreival Bot utilizing trigger Parameters.

void GivePopulationInfo(string cityName, string population)
{
var parameters = new Dictionary<string, string>
{
{ "city", cityName },
{ "population", population }
};

InworldController.Instance.SendTrigger("provide_population", m_InworldPlaygroundCharacter.ID, parameters);
}
goals: 
- name: "provide_population"
repeatable: true
activation:
trigger: "provide_population"
actions:
- instruction: "tell {player} the population of {{p.city}} is {{p.population}}."
emotion_change: JOY

- name: "unsupported_city"
repeatable: true
activation:
trigger: "unsupported_city"
actions:
- instruction: "apologize to {player} for not knowing the population of {{p.city}}."
emotion_change: SADNESS

For more information on utilizing Intents, Entities and/or Parameters, please see the corresponding links:

Interactable Items

The Interactable Items showcase is an example of how you can have an Inworld character react to the player interacting with objects in a scene.

This showcase utilizes Intents, Parameters and Character Mutations.

Interactable Items Showcase

Before you can interact with the items in the showcase you must first enable the interactable goals by greeting Mr. Toyman.

intents:
- name: "greeting"
training_phrases:
- "hi"
- "hello"
- "what's up"
- "yo"

goals:
- name: "greeting"
enabled_by_default: true
repeatable: false
activation:
intent: "greeting"
motivation: "player says hello"
actions:
- instruction: "Ask the player which item they are interested in"
send_trigger: enable_interactables
character_changes:
set_emotion: INTEREST
enable_goals:
- "item_interacted"
- "doll_interacted"
- "angry_interacted"

Once you have greeted Mr. Toyman you can interact with the Toy Rocket or Innequin Miniature by hovering over the object (the crosshair will turn green) and left-clicking with the mouse.

Interactable Items Innequin Miniature

Interacting with the Innequin Miniature will change its skin and trigger the item_interacted goal.

goals:
- name: "item_interacted"
enabled_by_default: false
repeatable: true
activation:
trigger: "item_interacted"
actions:
- instruction: "Acknowledge {player} {{p.action}} the {{p.item}} and tell them something about that {{p.item}}."

This object has the Material Change Interactable component attached to it which defines the action and item parameters in the item_interacted trigger sent from the client.

Interactable Items Innequin Miniature Inspector

Interacting with the Toy Rocket will cause it to fly into the air and fall off the platform.

Interactable Items Toy Rocket

This will trigger the angry_interacted goal which will cause Mr. Toyman to get angry at the player.

goals:
- name: "angry_interacted"
enabled_by_default: false
repeatable: false
activation:
trigger: "angry_interacted"
actions:
- instruction: "React to {player} for {{p.action}} the {{p.item}} worth {{p.price}} dollars."
character_changes:
set_emotion: ANGER
set_custom_dialogue_style:
set_adjectives:
- "annoyed"
- "1 sentence response"

Interactable Items Toy Rocket

The Toy Rocket object has the Apply Force Interactable component attached to it which defines the action, item and cost parameters in the angry_interacted trigger sent from the client.

Interactable Items Toy Rocket Inspector

For more information on utilizing Intents, Parameters, and/or Character Mutations please see the corresponding links:

Environmental Triggers

The Environmental Triggers showcase is an example of how you can utilize Goals and Intents to make an Inworld character interact with and/or react to their environment.

In this example we have Patrol Bot who can detect motion in two seperate areas. If they notice movement in one of those zones they will walk to that zone to check it out.

Environmental Triggers Showcase

Motion detection for Patrol Bot is handled by the client, in Unity we have an object with a Sphere Collider component as well as a custom On Trigger component on each platform.

Environmental Triggers Platform Inspector Environmental Triggers Colliders

The On Trigger component sends either a motion_area_a or motion_area_b trigger to Patrol Bot when the player collides with one of these objects as they walk onto a platform.

goals:
- name: "motion_area_a"
repeatable: true
activation:
trigger: "motion_area_a"
actions:
- send_trigger: "motion_area_a"
say_verbatim: "Motion detected in Area alpha. Moving out!"
- name: "motion_area_b"
repeatable: true
activation:
trigger: "motion_area_b"
actions:
- say_verbatim: "Motion detected in Area beta. On my way!"

This will activate the corresponding goal and send a trigger back to the client. On the client side we listen for these server triggers to determine when and where to move Patrol Bot. Movement is handled using Unity's AI Navigation system.

protected override void OnInworldCharacterGoalCompleted(string triggerName)
{
switch (triggerName)
{
case "motion_area_a":
case "request_area_a":
MoveTo(m_AreaATransform.position);
break;
case "motion_area_b":
case "request_area_b":
MoveTo(m_AreaBTransform.position);
break;
}
}

protected void MoveTo(Vector3 position)
{
if (NavMesh.SamplePosition(position, out NavMeshHit hit, 10, NavMesh.AllAreas))
{
m_CurrentDestination = new Vector2(hit.position.x, hit.position.z);

if (!IsAgentWithinStoppingDistance(m_CurrentDestination))
m_NavMeshAgent.SetDestination(hit.position);
}
}

Environmental Triggers Area Beta

Patrol Bot can also be commanded by the player to move to one of those two areas. This is handled through the request_area_a and request_area_b Intents.

goals:
- name: "request_area_a"
repeatable: true
activation:
intent: "request_area_a"
actions:
- say_verbatim: "Request to patrol Area alpha received."
- name: "request_area_b"
repeatable: true
activation:
intent: "request_area_b"
actions:
- say_verbatim: "Request to patrol Area beta received."

intents:
- name: "request_area_a"
training_phrases:
- "I need you to patrol area a"
- "Patrol area a"
- "I need you to patrol area alpha"
- "Patrol area alpha"
- "Go to a"
- "Go to alpha"

- name: "request_area_b"
training_phrases:
- "I need you to patrol area b"
- "Patrol area b"
- "I need you to patrol area beta"
- "Patrol area beta"
- "Go to b"
- "Go to beta"

When an intent is activated, the server will send a Goal Complete trigger, which will be handled by the client in the same way as triggers for motion detection are handled.

Environmental Triggers Walking

For more general information on using Goals with Inworld see here, for more information on using Goals with the Inworld Unity SDK, see the SampleGoals_Actions demo scene.