Relationships
A character's Relationship settings govern how they develop either a friendship or romance with the player.
Intro to Relationships
The video below offers a broad introduction to the Relationships system and the effect it can have on a character's interactions with the player.
Overview
A character can develop two types of relationships with users: Friendship and Romance.
These relationship types evolve through several distinct stages:
- Friendship: Archenemy ↔ Enemy ↔ Acquaintance ↔ Friend ↔ Close Friend.
- Romance: Date ↔ Relationship ↔ Life Partner.
Relationships can increase or degrade through stages depending on interactions with the player, allowing for a dynamic connection responds to the player's actions and choices.
Enabling Relationships
To enable Relationships system for a character, under their Advanced tab, flip the Enable Dynamic Relationships toggle.
Once Relationships have been enabled, you can set the Relationship Fluidity.
- Slower Changing results in the character less willing to change their relationship with the player.
- Faster Changing results in the character more willing to change their relationship with the player.
Relationship Influences
Characters' relationships change based on five distinct Relationship Influences.
These influences include:
- Trust vs Distrust
- Respect vs Contempt
- Familiar vs Distant
- Attraction vs Aversion
- Flirtatious vs Serious
How the character perceives their interactions with the player adds or subtracts from these Relationship Influences, updating the status of their relationship when the total value raises or lowers past a set threshold.
Relationship Influence Thresholds
The following thresholds are used to determine when a new stage in a relationship begins.
Influences | Friendship | Romance | ||||||
---|---|---|---|---|---|---|---|---|
Archenemy | Enemy | Acquaintance | Friend | Close Friend | Date | Relationship | Life Partner | |
Trust/Distrust | <0 | <0 | ≥50 | ≥100 | ≥200 | ≥50 | ≥100 | ≥200 |
Respect/Contempt | <-200 | <-50 | ≥0 | ≥50 | ≥200 | ≥0 | ≥50 | ≥100 |
Familiar/Distant | - | - | - | ≥100 | ≥200 | ≥50 | ≥100 | ≥200 |
Attraction/Aversion | <-200 | <-50 | ≥0 | ≥50 | ≥200 | ≥50 | ≥100 | ≥200 |
Flirtatious/Serious | <50 | <50 | <50 | <50 | <50 | ≥50 | ≥200 | ≥200 |
Relationships in Studio Chat
When chatting with a character using Inworld Studio, the chat window provides details on the increase or decrease for each Relationship Influence value based on your inputs, appearing as small orange or green arrows below chat replies.
- Green upwards arrows indicate an increase in relationship.
- Orange downwards arrows indicate a decrease in relationship.
These values persist between conversations and are associated with your Player Profile.
Relationships vs Emotions
Note that Relationship changes are distinct from Emotional changes that occur as a reaction to the player’s input.
These two systems operate independently from each other, although can often appear to work together when influencing the responses of a character.
Tracking Character Relationships in Runtime
There are a variety of ways the Relationships system tracks changes during runtime, detailed below based on platform.
Unreal SDK
Relationship changes are returned as a trigger from the On Trigger(Inworld Character) node, and can be tied to other actions that may be triggered by the change in relationship, such as a visual indicator (ie: hearts particle effect) or a change in the environment.
Example of the returned relationship label:
Trigger Name: inworld.relation.change
Trigger Params: {"label":"ACQUAINTANCE"}
Step Values (numerical value changes in the various Qualities) are not exposed in the Unreal Integration.
The trigger is only sent if a parameter changes entirely, such as from Acquaintance to Friend.
Save Session to Keep Changes
As when working with Long-Term Memory, it is recommended you Save the Session once a relationship change is detected in order for this change to persist.
In addition, when the project begins, a Restore from that saved session should be used in the StartSession node.
Unity SDK
In Unity, the relationship value changes for the Qualities are both (1) received and printed in the console, and (2) as part of the Unity v3 SDK demo scenes (you can see a visual representation of these value changes).
Returning Relationship Changes
Relationship changes are returned as an event from the onRelationUpdated parameter of the InworldCharacter script. Similar to Unreal, you can listen to this event on an EventListener on other GameObjects and have other actions that may be triggered by the change in relationship as well.
Shown below is an example of the returned Qualities changes detected in Unity, represented similarly to the Studio where each change is represented by Green or Red UI elements:
Using OneRelationUpdated
If needed, you can tie logic or events to be fired to the OnRelationUpdated() event that is thrown when there is a Label change to the relationship detected by Inworld.
Example script snippets:
/// <summary>
/// Gets/Sets the character's current relationship towards players. Will invoke onRelationUpdated when set.
/// </summary>
public RelationState CurrRelation
{
get => m_CurrentRelation;
set
{
if (m_VerboseLog)
InworldAI.Log($"{Name}: {m_CurrentRelation.GetUpdate(value)}");
m_CurrentRelation = value;
onRelationUpdated.Invoke();
}
}
protected virtual void ProcessPacket(InworldPacket incomingPacket)
{
onPacketReceived.Invoke(incomingPacket);
InworldController.Instance.CharacterInteract(incomingPacket);
switch (incomingPacket)
{
case ActionPacket actionPacket:
HandleAction(actionPacket);
break;
case AudioPacket audioPacket: // Already Played.
HandleLipSync(audioPacket);
break;
case ControlPacket controlPacket: // Interaction_End
break;
case TextPacket textPacket:
HandleText(textPacket);
break;
case EmotionPacket emotionPacket:
HandleEmotion(emotionPacket);
break;
case CustomPacket customPacket:
HandleTrigger(customPacket);
break;
case RelationPacket relationPacket:
HandleRelation(relationPacket);
break;
default:
Debug.LogError($"Received Unknown {incomingPacket}");
break;
}
}
protected virtual void HandleRelation(RelationPacket relationPacket) => CurrRelation = relationPacket.debugInfo.relation.relationUpdate;