[HOWTO]: How To Get Procedurally-Generated Barker Transform

Announcements, support questions, and discussion for the Dialogue System.
Post Reply
User avatar
Tony Li
Posts: 21679
Joined: Thu Jul 18, 2013 1:27 pm

[HOWTO]: How To Get Procedurally-Generated Barker Transform

Post by Tony Li »

If you're procedurally generating characters that bark and you want to get the transform of the barker in a conditions method (e.g., to determine which line to bark), use the technique below.

When the Dialogue System prepares a bark, it sets four Dialogue System Lua variables:
  • Variable["Actor"]: The display name actor in the dialogue database that is associated with the barker.
  • Variable["ActorIndex"]: The index into the Actor[] table for the barker.
  • Variable["Conversant"]: The display name associated with the actor being barked at. (The bark target.)
  • Variable["ConversantIndex"]: The index into the Actor[] table for the bark target.
You can access these in C# using DialogueLua.GetVariable(), such as:

Code: Select all

string barkerName = DialogueLua.GetVariable("Actor").asString;
If the barker is represented by a GameObject, the Dialogue System will use the GameObject's Dialogue Actor component. For example:

Code: Select all

// Procedurally generate a barker:
string barkerName = GenerateRandomName();
GameObject barkerGO = new GameObject(barkerName);
DialogueActor dialogueActor = barkerGO.AddComponent<DialogueActor>();
dialogueActor.actor = barkerName;
CharacterInfo.RegisterActorTransform(barkerName, barkerGO.transform);
Your custom condition can get the barker GameObject like this:

Code: Select all

string barkerName = DialogueLua.GetVariable("Actor").asString;
Transform barkerTransform = CharacterInfo.GetRegisteredActorTransform(barkerName);
WiktorWasowski
Posts: 2
Joined: Wed Sep 20, 2023 2:28 pm

Re: [HOWTO]: How To Get Procedurally-Generated Barker Transform

Post by WiktorWasowski »

Thanks - works nicely, but there's one problem.

I think your suggested approach doesn't take into consideration that the `barkerName` isn't guaranteed to be unique. If two procedural characters end up having the same name, one overwrites the registered transform of the previous one. I tried addressing it by changing methods like `RegisterActorTransform` and `UnregisterActorTransform` but it ended up being a rabbit hole - much more code would need to be changed to address that and I'd prefer to avoid this to because there's a fair chance I'll break something.

Any suggestions on how to get around this? Is there a single place I could safely set (procedurally) the name to something that also contains a unique ID but doesn't affect the actor's display name (which would also be set in a single place somewhere)? I could set the `actor` field inside the `DialogueActor` script to the transform name and create an additional `displayName` field to be used exclusively by the dialogue UI. Unless you recommend a different approach?
User avatar
Tony Li
Posts: 21679
Joined: Thu Jul 18, 2013 1:27 pm

Re: [HOWTO]: How To Get Procedurally-Generated Barker Transform

Post by Tony Li »

Hi,

You can create a new actor in your dialogue database at runtime, give it a unique Name, and set the Display Name to whatever you want (including duplicates). Then you can register the GameObject using the unique Name. In your conditions check, Variable["ActorIndex"] will contain the Name (sanitized) and Variable["Actor"] will contain the Display Name.

To do this, at runtime you'll create a new dialogue database in memory and use DialogueManager.AddDatabase() to add it to the Dialogue System's runtime master database, which will already contain the content in the dialogue database that's assigned to the Dialogue Manager's Initial Database field.

Example:

Code: Select all

// Create database:
var database = ScriptableObject.CreateInstance<DialogueDatabase>();

// Create a template, which provides helper methods for creating database content:
var template = Template.FromDefault();

// Create 5 actors all named "The Barker":
int baseActorID = template.GetNextActorID(DialogueManager.masterDatabase); // Prevent ID conflicts with other databases.
for (int i = 0; i < 5; i++)
{
    // Create actor in database:
    int actorID = baseActorID + i;
    string actorName = Guid.NewGuid().ToString().Replace("-", ""); // Use a GUID for actor Name.
    Actor actor = template.CreateActor(actorID, actorName, false);
    actor.fields.Add(new Field("Display Name", "The Barker", FieldType.Text));
    database.actors.Add(actor);
    
    // Create GameObject:
    GameObject barkerGO = new GameObject("The Barker");
    DialogueActor dialogueActor = barkerGO.AddComponent<DialogueActor>();
    dialogueActor.actor = actorName;
    CharacterInfo.RegisterActorTransform(actorName, barkerGO.transform);
}

// Add database to Dialogue System's runtime data:
DialogueManager.AddDatabase(database);
WiktorWasowski
Posts: 2
Joined: Wed Sep 20, 2023 2:28 pm

Re: [HOWTO]: How To Get Procedurally-Generated Barker Transform

Post by WiktorWasowski »

Thanks!

Although I am currently a bit too busy to test this right away, it looks like what I need. It's good to know the database can be edited at runtime.
User avatar
Tony Li
Posts: 21679
Joined: Thu Jul 18, 2013 1:27 pm

Re: [HOWTO]: How To Get Procedurally-Generated Barker Transform

Post by Tony Li »

Glad to help! To be clear, this doesn't edit the dialogue database asset that you normally edit in the Dialogue Editor window at design time. Instead, at runtime the Dialogue System loads database(s) into an in-memory database referenced by DialogueManager.masterDatabase. Initially this masterDatabase only contains the database that you've assigned to the Dialogue Manager's Initial Database field. But if you use the code above (i.e., DialogueManager.AddDatabase()), or use an Extra Databases component, it will merge that additional database into masterDatabase.
Post Reply