Page 1 of 2

Delays on conversations (again..)

Posted: Thu Sep 05, 2019 10:56 am
by nicmar
I'm really been pulling my hair today to get delays working properly in combination with animated bubbles, the typewriter and conversations.

I successfully subclassed StandardBarkUI, and rewrote it to use DoTween, and also a method I created to calculate the duration of the typewriter taking stop chars into account. It was very straight forward.

However, subclassing StandardUISubtitlePanel is a completely different beast. I guess it's due to handling of different windows opening and closing in relation to each other.

Here's what I want to do:

1) Start a conversation

2) Popup the bubble subtitle using DoTween (CustomStandardUISubtitlePanel->ShowSubtitle, replacing animatorMonitor.SetTrigger). The animation lasts for 0.3 seconds.

3) Delay the typewriter effect until 0.4 seconds (Edited UnityUITypewriterEffect)

Code: Select all

// This happens on line 260 before it starts typing
control.text = "<color=#00000000>" + control.text + "</color>";
if (delayBeforeStarting>0) yield return new WaitForSeconds(delayBeforeStarting); // private var
lastTime = DialogueTime.time; // Reset time due to delay
4) Play the typewriter for the duration of the text with the stop characters

5) When the typewriter is finished, wait for 1.5 seconds, then hide subtitle with DoTween (CustomStandardUISubtitlePanel->HideSubtitle, replacing animatorMonitor.SetTrigger)

6) Wait for 1 second, then open the next subtitle, and repeat.

The problem is in step 4/5, the subtitle closes before the text is completed, even if I don't have any stop characters.
I couldn't find where in the code the duration of the subtitle is set. It seems to just skip forward after a while depending on the text length/cps.

I'd like to override this, to use the characters per second + duration of the stop chars (I made a static method for that in DialogueUtils.cs).

I have this default sequence, that I think I got from the forum. I don't understand why there are double delays in the middle. Is there any point? But I think this solves problem 6.

Code: Select all

SetDialoguePanel(false)@{{end}}->Message(Wait);  
Delay(0.7)@Message(Wait)->Message(Hid);  
Delay(0.7)@Message(Hid)->Message(Delayed);  
SetDialoguePanel(true)@Message(Delayed)
I have attached the files that I have worked with as a ZIP. If you can give any advice, it would be very helpful. I'm considering scrapping everything and starting over, but I'm not sure where to start.

Thank you!

Attached files:
- CustomStandardBarkUI.cs (Subclass of StandardBarkUI)
- CustomUISubtitlePanel.cs (Subclass of StandardUISubtitlePanel)
- DialogueUtils.cs (Custom script to get duration with stop chars)
- UnityUITypewriterEffect.cs (Overwritten original, couldn't subclass it I think)

Re: Delays on conversations (again..)

Posted: Thu Sep 05, 2019 1:26 pm
by Tony Li
Hi,

One important thing to keep in mind: The conversation changes from the current node to the next node when the current node's Sequence is done. The subtitle panel has absolutely nothing to do with the timing*. For example, the player may have turned off subtitles.

* Exception: The typewriter effect sends the sequencer message 'Typed' when it's done. A Sequence can wait for this message.
nicmar wrote: Thu Sep 05, 2019 10:56 amHere's what I want to do:

1) Start a conversation

2) Popup the bubble subtitle using DoTween (CustomStandardUISubtitlePanel->ShowSubtitle, replacing animatorMonitor.SetTrigger). The animation lasts for 0.3 seconds.

3) Delay the typewriter effect until 0.4 seconds (Edited UnityUITypewriterEffect) <code snipped>

4) Play the typewriter for the duration of the text with the stop characters

5) When the typewriter is finished, wait for 1.5 seconds, then hide subtitle with DoTween (CustomStandardUISubtitlePanel->HideSubtitle, replacing animatorMonitor.SetTrigger)

6) Wait for 1 second, then open the next subtitle, and repeat.
What about this?

Set the Sequence to:

Code: Select all

WaitForMessage(NextNode)
Add a method to CustomStandardUISubtitlePanel called OnTypewriterEnd. Configure the typewriter effect's OnEnd() event to call OnTypewriterEnd.

In OnTypewriterEnd:
  • Call the Hide method, which should hide the subtitle using DOTween.
  • Wait 1 second.
  • Run this code:

    Code: Select all

    Sequencer.Message("NextNode");
You don't even really need to make a subclass of CustomStandardUISubtitlePanel. You could probably do all this in a new script attached to the Dialogue Manager that has an OnConversationLine method. But since you already have the subclass there's no harm continuing to use it.

If that doesn't work, let me know and I'll take a look at the scripts you attached and send you an example.

Re: Delays on conversations (again..)

Posted: Thu Sep 05, 2019 5:21 pm
by nicmar
Thank you for the interesting ideas! I was curious on the solution to put a new script attached to the Dialogue Manager that has an OnConversationLine, but I didn't figure out how I would access the current subtitle UI, to get a reference to the canvasGroup and rect to show it.

So I went for the other idea with OnTypewriterEnd. And I finally nailed it!

However you never mentioned anything about when to start the animation, so what I did was this in CustomStandardUISubtitlePanel (removed variables for clarity)

Code: Select all

protected override void Start() {
	base.Start();
	canvasGroup = GetComponent<CanvasGroup>();
	panel.localScale = Vector3.zero;
	canvasGroup.alpha = 0;
	typeWriter = GetComponentInChildren<UnityUITypewriterEffect>();
}

public void OnTypewriterBegin() {
	if (closeCoroutine != null) StopCoroutine(closeCoroutine);
	openCoroutine = StartCoroutine(nameof(CustomOpen));
}

public void OnTypewriterEnd() {
	if (openCoroutine != null) StopCoroutine(openCoroutine);
	closeCoroutine = StartCoroutine(nameof(CustomClose));
}


IEnumerator CustomOpen() {
	// Wait a frame to let typewriter start, and pause it
	yield return null;
	typeWriter.Pause();
	yield return new WaitForSeconds(durationBeforeAnimation);
	panel.DOScale(new Vector3(1, 1, 1), durationShow).SetEase(curveShow);
	DOTween.To(() => canvasGroup.alpha, x => canvasGroup.alpha = x, 1.0f, durationShow).SetEase(curveShow);
	yield return new WaitForSeconds(durationShow + durationBeforeTypeWriter);
	typeWriter.Unpause();
}

IEnumerator CustomClose() {
	yield return new WaitForSeconds(durationAfterTypeWriter);
	panel.DOScale(new Vector3(0, 0, 0), durationHide).SetEase(curveHide);
	DOTween.To(() => canvasGroup.alpha, x => canvasGroup.alpha = x, 0f, durationHide).SetEase(curveHide);
	yield return new WaitForSeconds(durationHide + durationUntilNextNode);
	Sequencer.Message("NextNode");
}
I also set the default sequence to WaitForMessage(NextNode) like you wrote.

I couldn't find an event to catch BEFORE the typewriter starts, and then manually start the typewriter once the animation is ready, but I guess pause worked just as well.

Can you see any gotchas here, that can cause any trouble?

What would happen if multiple typewriters is on at the same time, like somebody barking? Could/should I zone in on just this typewriter (the child) and its events?

Thank you again for your endless patience and great ideas.

Let me entertain you with a short clip of maybe 10 hours of work :D

Re: Delays on conversations (again..)

Posted: Thu Sep 05, 2019 9:14 pm
by Tony Li
nicmar wrote: Thu Sep 05, 2019 5:21 pmI couldn't find an event to catch BEFORE the typewriter starts, and then manually start the typewriter once the animation is ready, but I guess pause worked just as well.
I'll make StartTypingWhenFocused virtual in the next update. Someone can then override that to wait for DOTween before starting the typewriter. But pausing is fine.
nicmar wrote: Thu Sep 05, 2019 5:21 pmWhat would happen if multiple typewriters is on at the same time, like somebody barking? Could/should I zone in on just this typewriter (the child) and its events?
Yes, that's probably better, since Sequencer.Message() works globally. In the OnEnd() event, call the subtitle panel's OnContinue() instead. Change the Sequence to:

Code: Select all

WaitForMessage(Forever)
"Forever" is a made-up message. Since you won't be sending this message, it will wait forever. But by calling the panel's OnContinue() method, it will advance to the next node.
nicmar wrote: Thu Sep 05, 2019 5:21 pmLet me entertain you with a short clip of maybe 10 hours of work :D
Nice! That looks very polished. I'm not so sure about his recipe idea, though. :-)

Re: Delays on conversations (again..)

Posted: Fri Sep 06, 2019 2:01 am
by nicmar
Hehe, thanks for the feedback on the video! Forever and onContinue worked great!

Re: Delays on conversations (again..)

Posted: Mon Jan 18, 2021 4:21 pm
by nicmar
Hi Tony, I'm reviving this old thread as I still have problems.

The reason is that I currently have problems using the Standard UI Subtitle to display anything (probably some unity UI problem made by myself) so I chose "Use BarkUI" instead, as the dialog should look the same for both barks and conversations. I noticed in this thread I had some problems getting the BarkUI to work with conversations, and I think that's the problem I have now.

I have a simple conversation between two actors in the scene. The first thing I don't understand is that when the first actor has spoken, both actors run the Hide() command. Is that normal?

If I run OnContinue() in the Hide method of my subclass (CustomStandardBarkUI.cs), it crashes, as OnContinue runs Hide, which causes an endless loop. And the Hide() command in the parent class doesn't seem to advance the sequence, only hide the panel.

So how can I send a "i'm finished with the typewriter, advance to the next node" command from my subclass?

I'm attaching my script here, if you can see anything here.

I'm using DS 2.2.13, and I'm willing to upgrade if there's anything that might have changed since my last update that could help. :)

Thanks a lot!

Re: Delays on conversations (again..)

Posted: Mon Jan 18, 2021 4:55 pm
by Tony Li
Hi Niclas,

If you can get regular bubble subtitle panels to work, it may be easier in the long run.

Otherwise, if you're using BarkDialogueUI, I think the solution is:

1. Don't call OnContinue() in Hide().

2. In Start(), call base.Start() first.

3. Rely on the subtitle's Sequence to time the bark.
  • Tick the bark UI's Wait Until Sequence Ends checkbox.
  • Set the Sequence (or the Dialogue Manager's Default Sequence) to:

    Code: Select all

    Delay({{end}})
  • Set the Dialogue Manager's Subtitle Settings > Subtitle Chars Per Second to the same value as the bark UI typewriter effect's Characters Per Second.

Re: Delays on conversations (again..)

Posted: Tue Jan 19, 2021 1:15 am
by nicmar
Thanks you so much for the quick reply. But what are the advantages of using the subtitle panels? Am i missing some functionality?

Re: Delays on conversations (again..)

Posted: Tue Jan 19, 2021 2:04 am
by nicmar
Hey!
Now I've tried it, and it kind of works, but not fully. See the attached video.

When I used base.Start(), all that happens was that it disables the canvas, so it never shows up, conflicting with myself hiding it with alpha/scale to use with dotween. Was there supposed to be anything important initializing there?

I changed the Default Sequence to Delay({{end}}) and I have the same Subtitle Chars Per Second in the main settings as in the typewriter. However it seems like it always plays the subtitle for the "min subtitle seconds". I don't know if stop/pause characters can conflict with this as they would need a little extra delay, but not that much i think.

If the first subtitle is longer than "min subtitle seconds", the second subtitles plays on top of it. I attached a video and console log with some of my own debug too. I still find it curious that it hides both panels, but that might be intended.

Can you see what's going wrong here?

I'm trying a little bit more with WaitForMessage(Forever) but I can't really figure out how to send the OnContinue message in the Bark UI. I tried this when Dotween has closed the dialog box, which seems like the correct spot to continue the sequence, but nothing seemed to happen.

Code: Select all

DialogueManager.instance.SendMessage(DialogueSystemMessages.OnConversationContinue, (IDialogueUI) this, SendMessageOptions.DontRequireReceiver);
Now I'm switching over to the "normal subtitles" script instead, as I had that working before, but still this puzzles me.

Thanks :)


Re: Delays on conversations (again..)

Posted: Tue Jan 19, 2021 8:33 am
by Tony Li
If you can get overhead bubble subtitle panels working, that will solve all of the timing issues. So I recommend pursuing that if you can. Otherwise, here are replies to the bark questions:
nicmar wrote: Tue Jan 19, 2021 2:04 amWhen I used base.Start(), all that happens was that it disables the canvas, so it never shows up, conflicting with myself hiding it with alpha/scale to use with dotween. Was there supposed to be anything important initializing there?
It does a couple of things that you may or may not need. If your bark UIs are configured to move around to stay in the screen viewport, it records the original position so the next bark can start in the proper place above the character's head.
nicmar wrote: Tue Jan 19, 2021 2:04 amI changed the Default Sequence to Delay({{end}}) and I have the same Subtitle Chars Per Second in the main settings as in the typewriter. However it seems like it always plays the subtitle for the "min subtitle seconds". I don't know if stop/pause characters can conflict with this as they would need a little extra delay, but not that much i think.
The {{end}} value considers \. and \, control characters. Is Wait Until Sequence Ends ticked?