Coding characters entering and leaving conversations

Announcements, support questions, and discussion for the Dialogue System.
AoF
Posts: 241
Joined: Sun May 12, 2019 8:36 pm

Coding characters entering and leaving conversations

Post by AoF »

I'm making a first person view VN. Here's what a scene looks like:

I want to make it so that if I click on one of those characters, the other character leaves the scene by either moving off to the left or the right, depending on which edge is closer to them. When your conversation is over, I'd like the character that ran off to come back. This way, the scene will look like the above picture again so you can talk to the other person that was there if you want.

How would I organize something like this? I'm thinking I need two strings, like "characterExitedLeft" and "characterExitedRight". They will store the name of the character game object. When a conversation ends, an OnConversationEnd event will check if any of those fields are non-null. If the characterExitedLeft is non-null, it'll call AnimatorPlay(EnterFromLeft, characterExitedLeft). If the characterExitedRight is non-null, it'll call AnimatorPlay(EnterFromRight, characterExitedRight).

Does this make sense? Is there a better way to do this?
User avatar
Tony Li
Posts: 21079
Joined: Thu Jul 18, 2013 1:27 pm

Re: Coding characters entering and leaving conversations

Post by Tony Li »

That sounds fine. If you need to, in OnConversationStart() you can identify the unused character. The used characters' transforms are DialogueManager.currentActor and DialogueManager.currentConversant.
AoF
Posts: 241
Joined: Sun May 12, 2019 8:36 pm

Re: Coding characters entering and leaving conversations

Post by AoF »

Tony Li wrote: Tue Jul 30, 2019 2:28 pm That sounds fine. If you need to, in OnConversationStart() you can identify the unused character. The used characters' transforms are DialogueManager.currentActor and DialogueManager.currentConversant.
OK that's good to know. That will probably make my life easier.
AoF
Posts: 241
Joined: Sun May 12, 2019 8:36 pm

Re: Coding characters entering and leaving conversations

Post by AoF »

How do I figure out if a character in the scene is the DialogueManager.currentConversant or DialogueManager.currentActor?

Here's my hierarchy:



Here's my code:

Code: Select all

using PixelCrushers.DialogueSystem;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InactiveCharactersLeaveConversation : MonoBehaviour
{
    public void OnConversationStart(Transform actor)
    {
        foreach (var dialogueActor in Object.FindObjectsOfType<DialogueActor>())
        {

            var conversantName = DialogueManager.currentConversant.gameObject.name;
            var actorName = DialogueManager.currentActor.gameObject.name;
            if (dialogueActor.GetActorName() != "Player" && dialogueActor.GetActorName() != actorName && dialogueActor.GetActorName() != conversantName)
            {
                Debug.LogError("I would remove " + dialogueActor.GetActorName() + " " + dialogueActor.gameObject.name + " " + DialogueManager.currentConversant.gameObject.name + " " + DialogueManager.currentConversant.parent.gameObject.name);

                var xPosition = dialogueActor.transform.Find("Skeleton").position.x;
                if (xPosition > 0)
                {
                    DialogueManager.PlaySequence($"AnimatorPlay(LeaveHalfFromRight, {dialogueActor.GetActorName()})");
                }
                else if (xPosition < 0)
                {
                    DialogueManager.PlaySequence($"AnimatorPlay(LeaveHalf, {dialogueActor.GetActorName()})");
                }
            }
        }
    }
}

Here's what makes no sense to me: If I click on the Jessie, it says conversantName is "Skeleton". If I click on Shopkeep, it says conversantName is "Shopkeep". These two results are so unrelated, I can't figure out what could possibly cause it.

If there's a better way to write the above code, I don't mind throwing it away. I just want to find the names and positions of the characters that are not actors or conversants.
User avatar
Tony Li
Posts: 21079
Joined: Thu Jul 18, 2013 1:27 pm

Re: Coding characters entering and leaving conversations

Post by Tony Li »

Hi,

Thanks for sending the reproduction files. Your code works. There were just a few little issues that caused the conversation to use the wrong GameObject as the conversant. If the Dialogue System Trigger's Conversation Conversant field is unassigned, it will look for the GameObject that matches the conversation's Conversant assignment. Jessie's conversation was assigned to Olivia, so it wasn't finding the GameObject. In this case, it used the Dialogue System Trigger GameObject itself (Skeleton).
AoF
Posts: 241
Joined: Sun May 12, 2019 8:36 pm

Re: Coding characters entering and leaving conversations

Post by AoF »

Tony Li wrote: Wed Jul 31, 2019 11:45 am Jessie's conversation was assigned to Olivia
OK, thanks a lot for finding that. There are many places to pick/assign/use an "actor," but it seems like many of them don't matter in the end, until you try to do something you haven't done before, and then things work unexpectedly. For example, I was looking all over the GameObject and Skeleton and found lots of places to assign actors/conversants. I searched all over for differences between settings when all along the problem was in the conversation itself. I even looked at the Start node and saw that it was using Jessie before I asked my latest question here.

1. Is there any way to get warnings if I'm doing dumb things (like using Olivia as the conversant in the conversation, but never using her once anywhere in the conversation)? Better yet, is there any way to make it impossible for me to make dumb mistakes like that in the first place?
2. Perhaps the way DialogueManager.currentConversant finds its value should be documented right on the field in the source code?

Thanks!
User avatar
Tony Li
Posts: 21079
Joined: Thu Jul 18, 2013 1:27 pm

Re: Coding characters entering and leaving conversations

Post by Tony Li »

AoF wrote: Wed Jul 31, 2019 10:20 pm1. Is there any way to get warnings if I'm doing dumb things (like using Olivia as the conversant in the conversation, but never using her once anywhere in the conversation)? Better yet, is there any way to make it impossible for me to make dumb mistakes like that in the first place?
When a node uses the conversation's actor or conversant, it omits the character's name. If the node uses another character, it shows the name so you know it's not the conversation's actor or conversant. In the screenshot below, the top gray node is assigned to Olivia, who is also assigned as the conversation's conversant. The bottom two nodes are assigned to Jessie, who is neither the conversation's actor nor conversant:

conversants.png
conversants.png (9.75 KiB) Viewed 1299 times

In the Dialogue Editor's Actors section, you can also set a custom node color for each character.
AoF wrote: Wed Jul 31, 2019 10:20 pm2. Perhaps the way DialogueManager.currentConversant finds its value should be documented right on the field in the source code?
I'll do that.
AoF
Posts: 241
Joined: Sun May 12, 2019 8:36 pm

Re: Coding characters entering and leaving conversations

Post by AoF »

Tony Li wrote: Wed Jul 31, 2019 10:53 pm The bottom two nodes are assigned to Jessie, who is neither the conversation's actor nor conversant:
That's a really helpful tip.

There are lots of places where you can assign conversants and actors optionally.

For example:

- Dialogue System Trigger under start conversation
- Dialogue System Trigger under play sequence
- Dialogue Actor
- In a conversation
- In a node

In most cases, it's not obvious to me what the effect will be if I set these or leave them blank. There also seems to be lots of fallback logic, where if parts of the library can't find it in one place, they'll look in another. The order of where it looks first, when it looks, why it looks, etc. isn't clear to me. Is the order the same regardless of why it's looking, or does it change depending on the situation? Sorry, I know this question is a little vague, but I don't know what I don't know :)
I'll do that.
Great, thanks!
User avatar
Tony Li
Posts: 21079
Joined: Thu Jul 18, 2013 1:27 pm

Re: Coding characters entering and leaving conversations

Post by Tony Li »

While streamlining the manual when moving from version 1.x to 2.x, I inadvertently removed that information and didn't add it back. I'll get it into the next update. In the meantime:


NOTE: Actor GameObjects used in runtime conversations don't have to be the same as the actors assigned to the conversation in your dialogue database! See below for an explanation.

Conversation Actor & Conversant
When you create a conversation in the Dialogue Editor, you'll assign an actor and a conversant from the dialogue database's list of actors. Typically, the actor is the player and the conversant is the primary NPC involved in the conversation. To view or change the conversation's actor and conversant, click on empty canvas space to inspect the conversation's properties.

Dialogue Entry Node Actor & Conversant
As you add dialogue entry nodes, the editor will automatically assign an actor and conversant to the node. The node's actor is the character who is speaking. The node's conversant is the character being spoken to. To change a node's actor or conversant, click on the node to inspect its properties.

Dialogue System Trigger Actor & Conversant
When you set up a Dialogue System Trigger, you can assign GameObjects to the Start Conversation > Conversation Actor and Conversation Conversant fields. These GameObjects can represent different actors than those assigned to the conversation in your dialogue database.

The conversation will use these GameObjects even if they don't match the actors assigned to the conversation. This allows you to reuse conversations for different characters – for example, reusing the same shopkeeper conversation for all shopkeepers in your game world. (Tip: In your dialogue database, you can create a generic actor named "Shopkeeper" with a generic conversation such as: "Hello, I'm [var=Conversant]. Welcome to my shop!" etc. Then reuse the same shopkeeper conversation for each village's shopkeeper and simply assign the specific village shopkeeper to the Conversation Conversant field.)

Conversation Actor
If you don't assign the Conversation Actor field, the Dialogue System Trigger will try to choose an appropriate GameObject:
  • If the trigger type is OnTriggerEnter/Exit or OnCollisionEnter/Exit, it will use the GameObject that collided with the trigger.
  • If the trigger type is OnUse, it will use the GameObject that sent the "OnUse" message, typically the GameObject with a Selector or Proximity Selector component.
  • Otherwise it will look for a GameObject that has a Dialogue Actor component whose actor dropdown matches the conversation's actor. Failing that, it will look for a GameObject whose name matches the conversation's actor.
Conversation Conversant
If you don't assign the Conversation Conversant field, the Dialogue System Trigger will generally try to choose an appropriate GameObject:
  • It will look for a GameObject that has a Dialogue Actor component whose actor dropdown matches the conversation's conversant.
  • Failing that, it will use the Dialogue System Trigger GameObject.
Other Participants
If a dialogue entry node is assigned to an actor that is not the conversation's primary actor or conversant, it will look for a GameObject that has a Dialogue Actor component whose actor dropdown matches the node's actor. Failing that, it will look for a GameObject whose name matches the node's actor.
AoF
Posts: 241
Joined: Sun May 12, 2019 8:36 pm

Re: Coding characters entering and leaving conversations

Post by AoF »

OK that was very informative, thanks for sharing that. My favorite part is this:
The conversation will use these GameObjects even if they don't match the actors assigned to the conversation. This allows you to reuse conversations for different characters – for example, reusing the same shopkeeper conversation for all shopkeepers in your game world. (Tip: In your dialogue database, you can create a generic actor named "Shopkeeper" with a generic conversation such as: "Hello, I'm [var=Conversant]. Welcome to my shop!" etc. Then reuse the same shopkeeper conversation for each village's shopkeeper and simply assign the specific village shopkeeper to the Conversation Conversant field.)
I think it would help to see information like this on every section. This part doesn't just explain what, but why. To give another example, the node's documentation says:
The node's conversant is the character being spoken to. To change a node's actor or conversant, click on the node to inspect its properties.
From the documentation, I understand that I can change the node's conversant, but I have no idea why I'd want to. Why not leave it blank for every node? Why not set it to the wrong character? Why not set it to the same value as the actor? It's not obvious to me how this field is used. The documentation states that it exists, but not its purpose.
Post Reply