Page 1 of 1
Max Dialogue Buffer
Posted: Sun Nov 15, 2020 10:43 pm
by boz
Howdy,
I believe when the dialogue buffer gets too long, it starts causing slowdown issues for new dialogue. Like not scrolling all the way to the new text and an temporary fps drop when clicking continue.
Is there a way to set a max buffer? Or in other words, a point in which the dialogue stops being saved in the scrollback?
Re: Max Dialogue Buffer
Posted: Mon Nov 16, 2020 8:47 am
by Tony Li
Hi,
Yes, there is. How is your dialogue UI configured?
If you're using the Textline template or SMSDialogueUI component, set Max Messages to a non-zero value such as 20 or 50.
If you're using the StandardUISubtitlePanel component's Accumulate Text checkbox, you can trim the top of the buffer by adding a small script to the dialogue UI:
TrimSubtitleText.cs
Code: Select all
using UnityEngine;
using PixelCrushers.DialogueSystem;
public class TrimSubtitleText : MonoBehaviour
{
public int maxAccumulatedCharacters = 1000;
void OnConversationLine(Subtitle subtitle)
{
var subtitlePanel = (DialogueManager.dialogueUI as StandardDialogueUI).conversationUIElements.defaultNPCSubtitlePanel;
var accumulatedText = subtitlePanel.accumulatedText;
if (accumulatedText.Length > maxAccumulatedCharacters)
{
accumulatedText = accumulatedText.Substring(accumulatedText.Length - maxAccumulatedCharacters);
}
}
}
[EDIT: Fixed silly logic error.]
Re: Max Dialogue Buffer
Posted: Fri Nov 20, 2020 1:45 am
by boz
Thanks for the reply - so I just got a chance to test this.
I adapted the code a little to get it to work:
Code: Select all
using UnityEngine;
using PixelCrushers.DialogueSystem;
public class TrimSubtitleText : MonoBehaviour
{
public int maxAccumulatedCharacters = 1000;
void OnConversationLine(Subtitle subtitle)
{
var subtitlePanel = (DialogueManager.dialogueUI as StandardDialogueUI).conversationUIElements.defaultNPCSubtitlePanel;
var accumulatedText = subtitlePanel.accumulatedText;
if (accumulatedText.Length > maxAccumulatedCharacters)
{
string firstFiveHundredChars = accumulatedText.Substring(0, 500);
accumulatedText = DeleteStrTwoFromStrOne(accumulatedText, firstFiveHundredChars);
subtitlePanel.accumulatedText = accumulatedText;
}
}
public string DeleteStrTwoFromStrOne(string strOne, string strTwo)
{
return strOne.Replace(strTwo, "");
}
}
Without the added bits, it seemed to just swap out the bottom line and leave the remaining first 1000 characters.
However, it seems to sometimes catch the middle of a color tag and warp the rest of the dialogue.
My next task was to address this issue:
https://www.pixelcrushers.com/phpbb/vie ... 771#p20771
Will solving that likely give me the tools to solve this issue as well?
Thanks
Re: Max Dialogue Buffer
Posted: Fri Nov 20, 2020 8:37 am
by Tony Li
Sorry about that logic error. I just fixed it in my post above by changing the "Substring" line to:
Code: Select all
accumulatedText = accumulatedText.Substring(accumulatedText.Length - maxAccumulatedCharacters);
However, you're correct; in its current form it doesn't accommodate color codes. To handle color codes, you can make the script a little fancier:
TrimAndGrayPreviousTextSubtitlePanel.cs
Code: Select all
using UnityEngine;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using PixelCrushers.DialogueSystem;
public class TrimAndGrayPreviousTextSubtitlePanel : StandardUISubtitlePanel
{
// Only keep this many lines in the subtitle panel:
protected const int maxLines = 100;
protected const string grayOpenTag = "<color=#c0c0c0>";
protected const string grayCloseTag = "</color>";
protected const string pattern = @"<color=\w+>|<color=[#][\w|\d]+>|</color>";
public List<string> previousLinesWithoutColor = new List<string>();
public override void OnConversationStart(Transform actor)
{
base.OnConversationStart(actor);
previousLinesWithoutColor.Clear();
}
public override void SetContent(Subtitle subtitle)
{
if (previousLinesWithoutColor.Count == 1)
{
// If this is the first old line, wrap it in gray:
accumulatedText = grayOpenTag + previousLinesWithoutColor[0] + grayCloseTag;
}
else if (2 <= previousLinesWithoutColor.Count && previousLinesWithoutColor.Count < maxLines)
{
// If we're not at the max allowed lines yet, move the gray close tag to the end:
accumulatedText = accumulatedText.Replace(grayCloseTag, string.Empty) + grayCloseTag;
}
else if (previousLinesWithoutColor.Count >= maxLines)
{
// If we're at the max allowed lines, remove the topmost line from accumulatedText:
accumulatedText = grayOpenTag + accumulatedText.Substring(grayOpenTag.Length + previousLinesWithoutColor[0].Length);
accumulatedText = accumulatedText.Replace(grayCloseTag, string.Empty) + grayCloseTag;
previousLinesWithoutColor.RemoveAt(0);
}
base.SetContent(subtitle);
// Remove the possibly color-tagged current line from accumulated text, and add the non-color version:
accumulatedText = accumulatedText.Substring(0, accumulatedText.Length - (subtitle.formattedText.text + "\n").Length);
var currentLineWithoutColor = Regex.Replace(subtitle.formattedText.text, pattern, string.Empty) + "\n";
accumulatedText += currentLineWithoutColor;
previousLinesWithoutColor.Add(currentLineWithoutColor);
}
}
(Edit: Fixed with @boz's addition below.)
Re: Max Dialogue Buffer
Posted: Fri Nov 20, 2020 11:08 pm
by boz
Thanks!
That definitely did the trick, but I have no idea how it works.
I still managed to break it, but not consistently.
I'll have to do some studies on the techniques used here so I can fix it up to my liking.
Re: Max Dialogue Buffer
Posted: Sat Nov 21, 2020 9:18 am
by Tony Li
If you can identify any cases that break it, please let me know so I can update my post. This is the logic it uses:
Before displaying a new subtitle (called a "line" in the script):
- If we've already displayed exactly one line, wrap that old line in rich text that colors it gray.
- Otherwise if we're not at the max buffer size yet, accumulatedText will contain what's currently displayed, prior to showing the new line. Re-wrap all of this text in gray rich text.
- Otherwise, if we're at the max, remove the topmost line from accumulatedText. (Maybe there's a logic issue here, and it needs to re-wrap it all in gray?)
- Finally, add the new line to the accumulatedText in its original form, not gray.
Re: Max Dialogue Buffer
Posted: Sat Nov 21, 2020 8:20 pm
by boz
After looking up all the weird string manipulation code I've never seen before and defining every little bit, I started getting a hang of what was going on.
You were correct about where the look for the problem!
I copied this down to the 3rd if:
Code: Select all
accumulatedText = accumulatedText.Replace(grayCloseTag, string.Empty) + grayCloseTag;
Code: Select all
else if (previousLinesWithoutColor.Count >= maxLines)
{
// If we're at the max allowed lines, remove the topmost line from accumulatedText:
accumulatedText = grayOpenTag + accumulatedText.Substring(grayOpenTag.Length + previousLinesWithoutColor[0].Length);
//move the gray close tag to the end:
accumulatedText = accumulatedText.Replace(grayCloseTag, string.Empty) + grayCloseTag;
previousLinesWithoutColor.RemoveAt(0);
}
It made it easier to test when I moved maxLines down to like 10. I didn't realize the reason I wasn't seeing the issue consistently was because I was rarely hitting 100 lines when testing.
------------
My next challenge is to just try to replace the common text with the grey text and leave the other color tags. This is a good exercise to learn all of this stuff.
Thanks for your help as always
Re: Max Dialogue Buffer
Posted: Sat Nov 21, 2020 9:34 pm
by Tony Li
Thanks! I'll update my code above with your fixes in case someone in the future (myself, most likely) stops reading there and forgets to check further down.