0
\$\begingroup\$

I am working on a dialogue system and while the text part works, the UI for the Dialogue Boxes does not.

When I click on the Continue button, I want the script to go down the Elements [] and use the Image that I have selected there, similar to what the sentences[] feature does.

This is my script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;

public class TextDialogueScript : MonoBehaviour
{
    public TextMeshProUGUI textDisplay;
    public TextMeshProUGUI ContinueDialogue;
    public Image UIDisplay;
    public string[] sentences;
    public Image[] CharacterNames;
    public Sprite[] CharacterDialogueBox;
    public Image[] CharNames;
    //public List<Image> DialogueBoxes = new List<Image>();
    // public List<Image> CharacterName = new List<Image>();
    private int index;
    private int DBindex;
    public float typingSpeed;
    public GameObject DialogueTrigger;  
    public GameObject DialogueEventController;
    public GameObject NormalEeventController;

    // Start is called before the first frame update
    void Start()
    {
        NormalEeventController.SetActive(true);
        DialogueEventController.SetActive(false);
        UIDisplay.enabled = false;
        ContinueDialogue.enabled = false;
    }

    // Update is called once per frame
    void Update()
    {

        if(textDisplay.text == sentences[index])
        {
            ContinueDialogue.enabled = true;
        }

    }

    public void OnTriggerEnter(Collider other)
    {
        if(other.CompareTag("Player"))
        {
            NormalEeventController.SetActive(false);
            DialogueEventController.SetActive(true);
            StartCoroutine(Type());
            ContinueDialogue.enabled = true;
            UIDisplay.enabled = true;
            UIDisplay.sprite = CharacterDialogueBox[DBindex];
        }

    }

    public void OnTriggerStay(Collider other)
    {
        if (ContinueDialogue == true)
        {

        }
    }

    public void OnTriggerExit(Collider other)
    {
        NormalEeventController.SetActive(true);
        DialogueEventController.SetActive(false);
        ContinueDialogue.enabled = false;
        UIDisplay.enabled = false;
    }

    IEnumerator Type()
    {
        foreach(char letter in sentences[index].ToCharArray())
        {
            textDisplay.text += letter;
            yield return new WaitForSeconds(typingSpeed);
        }
    }

    public void NextSentence()
    {

        ContinueDialogue.enabled = false;

        if(index < sentences.Length - 1)
        {
            index++;
            textDisplay.text = "";
            StartCoroutine(Type());           
        }
        else
        {
            textDisplay.text = "";
        }

        if (DBindex < CharacterDialogueBox.Length - 1)
        {
            DBindex++;
        }

    }

}

I was using a List that grabbed sprites, but the problem is, it would only use Sprites from the Assets and not the Hierarchy. This is a problem because I have messed with the colours using Unity and played around with the Alpha to get the exact effect I want that cannot be replicated with my image program.

(I do not know what the term is for adding [] on the end of items to add elements that can be expanded. I have been stuck on this dialogue system for a very long time and I am very tired yet excited because I am so close to getting this to work, that it's painful)

\$\endgroup\$
10
  • \$\begingroup\$ You've cut this code a little too tightly for us to understand the context of what you're trying to do. First, this is not a code conversion problem, this is adding a new feature to your game, so describe the feature you want to add and how it should work. Then show your current dialogue script as a whole. \$\endgroup\$
    – DMGregory
    Commented May 15, 2020 at 14:49
  • \$\begingroup\$ @DMGregory I've added the full code now. What I am trying to do, is to recreate the NextSentence method but to work with Image[] instead. This is because in Unity under Elements, I am able to place the character's name and dialogue box images/sprites in order to match the dialogue and I thought this would be the best method to go about this. \$\endgroup\$ Commented May 15, 2020 at 15:32
  • \$\begingroup\$ I'm now trying to use a List<Image> instead of converting the code, since it may be the closest way of doing this. \$\endgroup\$ Commented May 15, 2020 at 16:35
  • \$\begingroup\$ It looks like you might be confused about naming. Image is a component that displays a Sprite. The Sprite is the visual that you want to cycle. \$\endgroup\$
    – DMGregory
    Commented May 15, 2020 at 17:57
  • \$\begingroup\$ I'm not surprised, there's still a lot I need to learn, however I've been getting a lot better and I'm actually really close to getting this to work :) I'm using a List<Image> and I've set up the Sprites I want to use in the Hierarchy, but the problem is, is that it will only allow me to use a Sprite from the Assets and not the Hierarchy. This is an issue because I've messed with the colouring in Unity on the sprite and it can't be replicated in my image program. I'm painfully close to getting it to work. \$\endgroup\$ Commented May 15, 2020 at 18:03

1 Answer 1

1
\$\begingroup\$

It looks to me like you might want to use some custom data structures for this.

First, one for your character:

[CreateAssetMenu(fileName="NewDialogueCharacter.Asset", menuName = "Dialogue/Character")]
public class DialogueCharacter : ScriptableObject {
    public Sprite portrait;
    public Sprite nameTag;
    public Color32 colour;
}

That will give you the ability to define new characters in your Asset folder using the Create menu, and set them up with a name, portrait, and tint colour that all fit together. This way, if you need to change something about the character, you can change it in one places, rather than having to search through every line of dialogue they speak to keep the changes in sync.

Example character creation

Next we'll define a type to store one beat of our dialogue:

[System.Serializable]
public struct DialogueBeat {
    public string text;
    public DialogueCharacter character;
}

Now your dialogue script can specify an array of DialogueBeats:

public class Dialogue : MonoBehaviour
{    
    public Image portrait;
    public Image namePlate;
    public TextMeshProUGUI textBlock;

    public DialogueBeat[] beats;
    int _currentBeatIndex;

    // ...
}

Which looks like this:

Dialogue inspector sample

This packages-together everything we need to display a particular part of the conversation in a single array, so we don't need to juggle multiple arrays and keep them in sync.

Your NextSentence method can then stay quite similar:

public void NextSentence()
{
    ContinueDialogue.enabled = false;

    textBlock.text = "";
    if(_currentBeatIndex < sentences.Length - 1)
    {
        _currentBeatIndex++;
        var beat = beats[_currentBeatIndex];
        textBlock.text = "";
        ShowCharacter(beat.character);
        StartCoroutine(Type(beat.text));           
    }
}

With minor teaks to typing sentences and displaying a new character:

IEnumerator Type(string text) {
     for(int i = 0; i < text.Length; i++) {
         textBlock.text = text.Substring(0, i);
         yield return new WaitForSeconds(typingSpeed);
     }

     // No need to check this in Update, just set it when we're done.
     ContinueDialogue.enabled = true;
}

void ShowCharacter(DialogueCharacter character) {
    if(character == null) {
        portrait.enabled = false;
        namePlate.enabled = false;
        return;
    }

    portrait.enabled = true;
    namePlate.enabled = true;
    portrait.sprite = character.portrait;
    portrait.color = character.colour;
    namePlate.sprite = character.nameTag;        
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .