Page 1 of 2

Procedural characters?

Posted: Tue May 19, 2020 9:35 pm
by timbecile
I was just looking at quest machine and saw that it has procedural quests (which I will be checking out), but I wondered if Dialogue System had a way to create procedural NPCs (to talk and give out those quests)

I am planning a pretty big game world, and I think I'm going to have to fill it with random villages (which will require random NPCs) and then random quests.

Any thoughts on that?

Re: Procedural characters?

Posted: Wed May 20, 2020 8:38 am
by Tony Li
Hi,

Yes. Since the Dialogue System doesn't tie conversations to specific GameObjects, you can re-use conversations as mentioned in Character GameObject Assignments. You can also leverage variables to customize those conversations.

For example, you can add a Dialogue Actor to each procedurally-generated NPC, and set its actor name to a randomly-generated name. When you start a conversation with this NPC as the conversant, it will use the name set in the Dialogue Actor component. You can show that name in Dialogue Text using [var=Conversant]:
  • Dialogue Text: "Hi, I'm [var=Conversant]!"
You can also set other other variables, reference them in Dialogue Text, and use them in Conditions. For example, say you have a script like this:

Code: Select all

public class CharacterDetails : MonoBehaviour
{
    public string hometown;
    public bool likesRain;
    
    void OnConversationStart(Transform actor)
    {
        DialogueLua.SetVariable("Hometown", hometown);
        DialogueLua.SetVariable("LikesRain", likesRain);
    }
}
Then you can have Dialogue Text like:
  • Dialogue Text: "I'm from [var=Hometown]. We have the best BBQ there."
and you can check Conditions such as:
  • Conditions: Variable["IsRaining"] and Variable["LikesRain"]
  • Dialogue Text: "I love a good downpour. It feels so cleansing."
You can also use RandomElement() to add a little variety:
  • Dialogue Text: "I love a good [lua(RandomElement("downpour|shower|spring rain")]. It feels so cleansing."

Re: Procedural characters?

Posted: Wed May 20, 2020 11:10 am
by timbecile
I think this is exactly what I was hoping for.

So you can randomize some of the words in a conversant text, but can you pull entire conversation trees from somewhere to build a random Dialog Actor or does the Dialog Actor have to be already written?

Re: Procedural characters?

Posted: Wed May 20, 2020 1:15 pm
by Tony Li
You can pull entire conversations. Here are a couple of ways you can approach it:
  • You can set some variables on the NPC, always start the same "hub" conversation for every NPC, and branch to different conversations (or different branches of the same conversation) based on the variable values.
  • Or when you create an NPC you can assign a conversation -- e.g., shopkeeper conversation, wandering villager conversation, bandit conversation, etc.

Re: Procedural characters?

Posted: Wed Feb 24, 2021 7:24 pm
by timbecile
Hi Tony,

I've turned my attention back to this, and am wondering if there is a way to randomly assign conversations. I'm thinking of getting all conversations within a folder (town/type/character) into a list, and then choosing from that list to assign it to a character.

is there a method for doing that?

Re: Procedural characters?

Posted: Wed Feb 24, 2021 7:33 pm
by Tony Li
Hi,

There are some ways you could do it:

1. Always start the same hub conversation. Link the hub's <START> node to an empty node. Link the empty node to all of the other conversations. Set the Sequence field to:

Code: Select all

required RandomizeNextEntry(); Continue()
If you don't require continue button clicks, you can simplify the Sequence to: RandomizeNextEntry()

2. Or, in a script, randomly assign a value to the Dialogue System Trigger's conversation property. For example, to assign a random conversation whose title starts with "Towns/Cloud Village/":

Code: Select all

List<string> conversations = DialogueManager.masterDatabase.conversations.FindAll(x => x.Title.StartsWith("Towns/Cloud Village/");
GetComponent<DialogueSystemTrigger>().conversation = conversations[Random.Range(0, conversations.Count)];
3. Or make a subclass of DialogueSystemTrigger and override the DoConversationAction() method. Something like:

Code: Select all

protected override void DoConversationAction(Transform actor)
{
    conversation = ((some random conversation title))
    base.DoConversationAction(actor);
}

Re: Procedural characters?

Posted: Wed Feb 24, 2021 7:41 pm
by timbecile
perfect. Option 2 is what I was looking for.

I was going to tie this into the saver system, so is there a way to save that conversation?

Re: Procedural characters?

Posted: Wed Feb 24, 2021 8:06 pm
by Tony Li
You could write a saver script that saves that conversation title. Example:

Code: Select all

using UnityEngine;
using PixelCrushers;
using PixelCrushers.DialogueSystem;

public class DialogueSystemTriggerConversationSaver : Saver
{
    public override string RecordData()
    {
        return GetComponent<DialogueSystemTrigger>().conversation;
    }
    
    public override void ApplyData(string s)
    {
        if (!string.IsNullOrEmpty(s))
        {
            GetComponent<DialogueSystemTrigger>().conversation = s;
        }
    }
}

Re: Procedural characters?

Posted: Wed Feb 24, 2021 8:14 pm
by timbecile
perfect. thanks!

Re: Procedural characters?

Posted: Wed Feb 24, 2021 8:56 pm
by Tony Li
Glad to help!