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 Room

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 Innequin.

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 causes the Rhyme Innequin to make up a rhyme with the given phrase.

For example, if you input the phrase "apples" Rhyme Innequin comes 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 a 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 Innequin, this activates the greeting intent which enables 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 Innequin 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 Innequin to walk right activates the corresponding goal, which in turn disables the right goal and enable the left goal. The Goals Innequin then walks toward the right.

Enable Goals with Intents Walking

Similarly asking Goals Innequin to walk left disables the left goal and enables 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 Innequin 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 Innequin listens for the player to ask what the population is in a particular city. This activates the get_population_goal goal which returns 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 there is a listener for these triggers sent by the server.

When a trigger is received by the client, this listener first checks 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) it is possible to attempt to fetch the data on the client. In this case the data is being fetched 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 Retrieval Innequin 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

Data Retrieval New York City

For more information on utilizing Intents, Entities and/or Parameters, 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 Innequin who can detect motion in two separate areas. If they notice movement in one of those zones, they walk to that zone to investigate.

Environmental Triggers Showcase

Motion detection for Patrol Innequin 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 Innequin 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 activates 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 Innequin. 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 Innequin 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 sends a Goal Complete trigger, which is 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.