Search Unity

Unity UI [SOLVED] How would you implement phone text messenger style UI?

Discussion in 'UGUI & TextMesh Pro' started by James-Sullivan, Jun 10, 2019.

  1. James-Sullivan

    James-Sullivan

    Joined:
    Jun 15, 2015
    Posts:
    128
    How would you implement a phone text messenger kind of UI in Unity? The game needs to be able to dynamically add text objects by code to the conversation and you can scroll through them when it gets longer than the screen.

    This is something I've been struggling with for a few days now and I can't find any workable solutions. Using a scroll rect seems to make sense. You parent the text boxes to a parent rect which you can then scroll up and down. But the issue with that is that you need to resize the parent rect when it runs out of space, and instead of adding the new space to the bottom of the rect, the space gets added evenly between all of the child elements so that they maintain their relative positions within the parent object. That is not what I want.

    I've also looked into vertical layouts, but that seems to be more for static menus rather than dynamic UI and has similar problems with wanting to space out child elements.

    Do you know of any better ways to go about this, or better yet, an example project that implements something like this? And controlling UI elements through code in general seems to be a pain in the ass, so maybe there's something larger I'm missing?
     
  2. James-Sullivan

    James-Sullivan

    Joined:
    Jun 15, 2015
    Posts:
    128
    I've figured out a reasonable solution. It just took some wrestling with the UI API to figure out how to control the rect transforms from the code. I attached a zip file with the required scene, prefab, and script. The prefab object being anchored to the top of its parent object is critical.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. // The dialogue manager is responsible for adding new dialogue boxes to the conversion when requested
    6. public class DialogueManager : MonoBehaviour {
    7.  
    8.     [SerializeField] private GameObject dialogueContainer;
    9.     [SerializeField] private GameObject textBoxPrefab;
    10.  
    11.     RectTransform containerRectTrans;
    12.  
    13.     // Keeps track of the transform of the previous addition
    14.     private RectTransform lastRectTrans = null;
    15.  
    16.     void Awake ()
    17.     {
    18.         containerRectTrans = dialogueContainer.GetComponent<RectTransform>();
    19.     }
    20.  
    21.     void AddDialogueBox()
    22.     {
    23.         RectTransform containerRectTrans = dialogueContainer.GetComponent<RectTransform>();
    24.  
    25.         GameObject newBox = Instantiate(textBoxPrefab, dialogueContainer.transform, false) as GameObject;
    26.         RectTransform newRectTrans = newBox.GetComponent<RectTransform>();
    27.  
    28.         // If this isn't the first dialog box being added
    29.         if (lastRectTrans != null)
    30.         {
    31.             Vector2 newPos = new Vector2(lastRectTrans.localPosition.x,
    32.                                          lastRectTrans.localPosition.y - newRectTrans.rect.height);
    33.  
    34.             newRectTrans.localPosition = newPos;
    35.  
    36.         }
    37.  
    38.         lastRectTrans = newRectTrans;
    39.  
    40.         CheckContainerLength();
    41.     }
    42.  
    43.     // Checks if the dialogue items have ran off the container length and adjusts accordingly
    44.     void CheckContainerLength()
    45.     {
    46.         // If the last item goes off the bottom edge of the container
    47.         if (containerRectTrans.rect.y > lastRectTrans.localPosition.y)
    48.         {
    49.             float extendDistance = Mathf.Abs(lastRectTrans.rect.y) + lastRectTrans.rect.height/2;
    50.          
    51.             // Resizing the container extends it in both directions, so we must reposition it accordingly
    52.             Vector2 newPos = new Vector2(containerRectTrans.localPosition.x,
    53.                                          containerRectTrans.localPosition.y - extendDistance/2);
    54.  
    55.             containerRectTrans.sizeDelta = new Vector2(0f, containerRectTrans.sizeDelta.y + extendDistance);
    56.             containerRectTrans.localPosition = newPos;
    57.         }
    58.     }
    59.  
    60.  
    61.     void OnGUI()
    62.     {
    63.         if (GUI.Button(new Rect(20, 40, 100, 200), "Add box" ))
    64.         {
    65.             AddDialogueBox();
    66.         }
    67.     }
    68. }
    69.  
     

    Attached Files:

    nanolu and NadaMostafa like this.