Search Unity

Character portrait in dialogue system

Discussion in 'Scripting' started by Soarino, Nov 24, 2017.

  1. Soarino

    Soarino

    Joined:
    Nov 16, 2017
    Posts:
    23
    I've already made a thread trying asking to fix my attempt at this but it didn't go anywhere fast, Ive already coded a dialogue system in which the character can talk to NPC but i wish to now add character portraits with changing emotions depending on the sentence being said


    This is a 3D game and the UI shows the dialogue box

    my scripts:

    My dialogue manager

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using UnityStandardAssets.Characters.FirstPerson;
    6.  
    7.  
    8. public class DialogueManager : MonoBehaviour {
    9.  
    10.     public Text nameText;
    11.     public Text dialogueText;
    12.     public GameObject fpsController;
    13.     public Animator animator;
    14.  
    15.     private Queue<string> sentences;
    16.  
    17.     // Use this for initialization
    18.     void Start() {
    19.         sentences = new Queue<string>();
    20.  
    21.     }
    22.  
    23.     public void StartDialogue(Dialogue dialogue)
    24.     {
    25.         fpsController.GetComponent<FirstPersonController>().enabled = false;
    26.         Cursor.visible = true;
    27.         Cursor.lockState = CursorLockMode.None;
    28.  
    29.         animator.SetBool("IsOpen", true);
    30.  
    31.         Debug.Log("Starting conversation with " + dialogue.name);
    32.  
    33.         nameText.text = dialogue.name;
    34.         sentences.Clear();
    35.  
    36.         foreach (string sentence in dialogue.sentences)
    37.         {
    38.             sentences.Enqueue(sentence);
    39.         }
    40.  
    41.         DisplayNextSentence();
    42.  
    43.     }
    44.  
    45.     public void DisplayNextSentence()
    46.     {
    47.         if (sentences.Count == 0)
    48.         {
    49.             EndDialogue();
    50.             return;
    51.         }
    52.  
    53.         string sentence = sentences.Dequeue();
    54.         StopAllCoroutines();
    55.         dialogueText.text = sentence;
    56.         StartCoroutine(TypeSentence(sentence));
    57.     }
    58.  
    59.     IEnumerator TypeSentence (string sentence)
    60.     {
    61.         dialogueText.text = "";
    62.         foreach (char letter in sentence.ToCharArray())
    63.         {
    64.             dialogueText.text += letter;
    65.             yield return null;
    66.         }
    67.     }
    68.  
    69.     void EndDialogue()
    70.     {
    71.         animator.SetBool("IsOpen", false);
    72.         Debug.Log("End of Conversation.");
    73.         fpsController.GetComponent<FirstPersonController>().enabled = true;
    74.         Cursor.visible = false;
    75.     }
    76.  
    77. }
    and my dialogue script

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5.  
    6. [System.Serializable]
    7. public class Dialogue {
    8.  
    9.     public string name;
    10.  
    11.     [TextArea(3, 10)]
    12.     public string[] sentences;
    13.  
    14.  
    15. }
    16.  

    I've only started coding and using unity for 2 weeks so im very much a noob, this is a learning process for me


    Please any help will be great!
     
  2. fire7side

    fire7side

    Joined:
    Oct 15, 2012
    Posts:
    1,819
    Stick with BlackEye Pete and he should get you through it eventually. It just takes a while sometimes. It would have been better to do some other tutorials before you tried a project like this but it seems like you are making progress.
     
  3. lordconstant

    lordconstant

    Joined:
    Jul 4, 2013
    Posts:
    389
    In your dialogue manager add a dictionary of strings & animations. Use this for getting the right emotion animation.

    In your dialogue class add a string called emotion, that will be the emotion to play during that dialogue. If you need it per line make a new class have the emotion & a string then replace the places where its just a string with your new class.

    Then you just need to grab the animation thats in the dictionary for your emotion key.
     
  4. Soarino

    Soarino

    Joined:
    Nov 16, 2017
    Posts:
    23
    When you say animations do you refer to the 3d model? I was thing about a 2d portrait very much like fire emblem
     
  5. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    Stick with the other post instead of double posting. Making a new post when you're already getting help is a bit disrespectful to the people trying to help you.
     
  6. lordconstant

    lordconstant

    Joined:
    Jul 4, 2013
    Posts:
    389
    You can import 2d animations aswell (although not had much personal experience). Also as @Brathnann has said stick to one thread, the replies will be better focused as people figure out your situation more.
     
  7. Soarino

    Soarino

    Joined:
    Nov 16, 2017
    Posts:
    23
    I've already resolved my problem on the other thread and i made this one to get help with implementing the character emotions, i forgot to mention that on the other thread. So the unique character portrait are in place just need help with changing them per sentence
     
  8. Soarino

    Soarino

    Joined:
    Nov 16, 2017
    Posts:
    23
    Is there not a way to run the changing of the character portrait in a array with what sentence element is current being outputted?
    So say the script starts with the sentence 0 and it would also start with the character portrait 0 then it would run to how many elements are in both arrays?
    Im asking this because i wouldn't know how to implement this into my code.
     
  9. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    I would embed some markup in your sentences that would reference the emotions, like a wikipedia page or code tags here on the forum.

    {excited}Oh, hi!{happy}How are you?{sad}Did you hear what happened to papa?

    Then just parse your text for the data and you're off to the races.
     
  10. Soarino

    Soarino

    Joined:
    Nov 16, 2017
    Posts:
    23
    How would i define my emotions though for the markup to know which sprite is being called to the UI?
     
  11. Errorsatz

    Errorsatz

    Joined:
    Aug 8, 2012
    Posts:
    555
    What I'd probably do is have a ScriptableObject for each character and include a mapping like:
    Code (csharp):
    1. [Serializable]
    2. public class EmotionEntry {
    3.    public string id;
    4.    public Sprite sprite;
    5. }
    6. ...
    7. public List<EmotionEntry> emotions;
    With a custom inspector if you're feeling fancy. But you could also define this in an external file and use Resources.Load.
    Also if the portraits have any animation/effects, then you'd want to have a prefab reference to instantiate instead of a Sprite.
     
  12. Soarino

    Soarino

    Joined:
    Nov 16, 2017
    Posts:
    23
    This works great! but how do i reference this in my dialogue manager so that it know to replace the placeholder with the emotions?

    I've tried something and I can't seem to reference it properly
     
    Last edited: Nov 28, 2017
  13. Errorsatz

    Errorsatz

    Joined:
    Aug 8, 2012
    Posts:
    555
    Do you have multiple characters with their own portraits, or just one?

    If it's the latter, then just add it as a field to your DialogueManager:
    Code (csharp):
    1. public CharacterInfo charInfo; // Or whatever your ScriptableObject class is called.
    2. public Image portait;
    3. ...
    4. private void SetEmotion (string emotion) {
    5.    var sprite = charInfo.emotions.FirstOrDefault(x => x.id == emotion);  // This is using System.Linq.  You could also do this manually with a loop.
    6.    if(sprite == null) {
    7.       Debug.LogError("Emotion {" + emotion + "} does not exist for the character.");
    8.    } else {
    9.       portrait.sprite = sprite;
    10.    }
    11. }
    If it's the former, then you'll need another mapping (of character id to CharacterInfo), which could be set up just like the emotion mapping, then have that as a field of DialogueManager.

    Also, this is a barebones example; it would probably be cleaner to have the character info class have a function to get a given emotion and have missing emotions handled there, rather than doing it in DialogueManager.