What's the way to know when a conversation line is fully displayed?

Announcements, support questions, and discussion for the Dialogue System.
Post Reply
Jdedueass
Posts: 10
Joined: Wed Aug 18, 2021 3:17 am

What's the way to know when a conversation line is fully displayed?

Post by Jdedueass »

Hi!
I'm trying to make the mouth of my NPC's move during conversations. Thing is, it works great! But I'd like to stop the mouth animation once a conversation line is fully displayed and the system is waiting for the player to press the continue button.

My first attempt was using OnConversationLineEnd, but this event is called once the player presses the continue button, so it does not work for my use case.

Is there another event or some built-in way in the plugin to know when a conversation line is fully displayed?
User avatar
Tony Li
Posts: 21977
Joined: Thu Jul 18, 2013 1:27 pm

Re: What's the way to know when a conversation line is fully displayed?

Post by Tony Li »

Hi,

If you're talking about the end of the typewriter effect, it sends the sequencer message "Typed" to the sequencer when it's done. You can use a Sequence (or Dialogue Manager > Default Sequence) like this:

Code: Select all

AnimatorPlay(Talk);
required AnimatorPlay(Idle)@Message(Typed)
In the example above, the first line plays the "Talk" animation on the speaker. The second line plays the "Idle" animation when the typewriter is done, and 'required' guaranteees that the command runs even if the player skips ahead. (Technically the typewriter always sends Typed even if the player skips ahead, but it's good practice to use required for end-of-sequence commands like this that must run.)
Jdedueass
Posts: 10
Joined: Wed Aug 18, 2021 3:17 am

Re: What's the way to know when a conversation line is fully displayed?

Post by Jdedueass »

Hi Tony and thank you!

Indeed, my aim is to stop the talk animation once the typewritter effect has stopped, and with the sequencer works awesome!

But I have a problem, and I can't find the way to replicate it in code, which is what I'd like to do. I'm not sure if I'll be clear enough but this is what I'm trying to achieve in pseudocode:

Code: Select all

class NPCStateMachine{
  	bool typewritterFinished = false;
  	
  	void OnTypeWritterEnd{
  		typewritterFinished = true;
  	}
  	
  	// Alternatively
  	//void SetupSequencer(){
        //   if(@Message(Typed))
        //        typeWritterFinished = true;
        //   else(@Message(TypedStarted)
        //        typeWritterFinished = false;
  	//}
  	
  	//void Awake(){ SetupSequencer(); }
  	
  	void Update(){
  	  if(typewritterFinished)
  	  	animation.StopTalking();
  	}
  	
}
I'm sorry if you already have answered this in the documentation, but I can't seem to find my way on it, I took a look to this page.https://www.pixelcrushers.com/dialogue_ ... ences.html
User avatar
Tony Li
Posts: 21977
Joined: Thu Jul 18, 2013 1:27 pm

Re: What's the way to know when a conversation line is fully displayed?

Post by Tony Li »

You want your NPC state machine to react to the end-of-typing message instead of using sequencer commands, correct?

If so, here are two options:

1. Still use a sequencer command to listen for "Typed", but make it inform your state machine instead of directly controlling the animation. Example:
  • Sequence: SendMessage(FinishedTyping)@Message(Typed)

Code: Select all

// In your state machine on the speaker:
public void FinishedTyping()
{
    animation.StopTalking();
}
Alternatively, write a custom sequencer command. They're fairly simple to write, and it might make your sequence simpler to read, such as:
  • Sequence: StopTalking()@Message(Typed)

2. Or hook into the typewriter's OnEnd() UnityEvent. Add a script with an OnConversationLine method similar to this to the speaker:

Code: Select all

UnityUITypewriterEffect myTypewriterEffect; // Or TextMeshProTypewriterEffect if using TMPro

void OnConversationLine(Subtitle subtitle)
{
    if (subtitle.speakerInfo.transform == this.transform &&
        !string.IsNullOrEmpty(subtitle.formattedText.text))
    {
        // I'm speaking this line, hook into the typewriter effect:
        DialogueActor dialogueActor;
        var panel = DialogueManager.standardDialogueUI.conversationUIElements.standardSubtitleControls.GetPanel(subtitle, out dialogueActor);
        myTypewriterEffect = panel.subtitleText.GetComponent<UnityUITypewriterEffect>();
        
        if (myTypewriterEffect != null)
        {
            myTypewriterEffect.onEnd.AddListener(HandleTypingEnded);
        
            // Start talking:
            myStateMachine.StartTalking();
        }
    }
}

// This method is called by the typewriter's OnEnd() event since we hook it up to the event.
void HandleTypingEnded()
{
    // Unhook from the event:
    myTypewriterEffect.onEnd.RemoveListener(HandleTypingEnded);
    
    // Stop talking:
    myStateMachine.StopTalking();
}
Jdedueass
Posts: 10
Joined: Wed Aug 18, 2021 3:17 am

Re: What's the way to know when a conversation line is fully displayed?

Post by Jdedueass »

Thanks Tony!!

The second option you mentioned is exactly what I'm looking for.

Thank you very much since I wasnt able to get it working by myself.
User avatar
Tony Li
Posts: 21977
Joined: Thu Jul 18, 2013 1:27 pm

Re: What's the way to know when a conversation line is fully displayed?

Post by Tony Li »

Happy to help! :-)
Post Reply