In-game GUI Label

Hi,

What I am trying to do is 'stack' my GUI label displayed statements one after the other. For example, when particles collide with a trigger, we display the GUI: Particles Collided. The second time particles collide, we display: Particles Collided again. What happens is that the GUI goes away, or they overlap each other.

Is their a way I can stack each GUI one after the other? Kind of like this:

Particles Collided

Particles Collided Again!

...Repeat every time particles collide

Edit

I made a very crude example of a GUI that gets printed whenever I step onto a trigger. Its not stacking, again the question remains unachieved: How can I stack GUI Text Statements?

public class MyMessages : MonoBehaviour 
{

    List<Messages> MessageList = new List<Messages>( )
;

    void Update()
    {

        /*foreach (Messages msg in MessageList)
        {
            MessageList.Remove(msg);
        }*/

    }

    public class Messages
    {
        string newMessage;

        public Messages(string msg/*, Vector2 pos, Color txtColor, Font txtFont*/)
        {
            // Format the message
            /*
            Vector2 Position;
            Color myColor;
            Font myFont; */

            newMessage = msg;
            Draw();
        }

        public void Draw()
        {
            Debug.Log("Start to Draw");
            GUI.Label(new Rect(pos.x, pos.y, pos.z, pos.w), newMessage);
        }
    }

    void OnGUI()
    {
        if (onTrigger) {
        string myMessage = "On Trigger";
        pos.x = 600; pos.y = 46; pos.z = 100; pos.w = 200;
        Messages m = new Messages(myMessage);
        }

        if (ParticleCollisonVar.x <= 1)
        {
            string myMessage = "Particles Collided!";
            pos.x = 520; pos.y = 500; pos.z = 1000; pos.w = 2000;

            Messages m = new Messages(myMessage);

            // Stack each time the above condition is true?
            foreach (Messages msgs in MessageList)
            {
                MessageList.Add(msgs);
            }
        }
    }
}

Would this be easier to achieve with the Game Object->Other->GUI Text ?

3 Answers

3

There isn't anything built-in from Unity that can make this happen, you need to code your own stacking display.

Luckily for you, I coded such a system for an old game I did in Unity. I'll paste the code here, but do NOT copy and paste this! It has game-specific features in it, and hard-coded positions in it that probably won't work in your game. Look at the code, and understand how you create a list of messages that can be stacked on one another.

///////////////////////////////////
// DO NOT COPY AND PASTE THIS!!!
///////////////////////////////////

using UnityEngine;
using System.Collections.Generic;

public class Messages : MonoBehaviour
{
    public Texture2D Background;
    List<Message> MessageList = new List<Message>();
    List<Message> toRemove = new List<Message>();

    public Font boldFont;

    public void AddBoldMessage(string newMessage, Color color)
    {
        foreach (Message ms in MessageList)
        {
            if (ms.Text == newMessage)
            {
                // Don't flood the user with the same message!
                return;
            }
        }

        int lowPoint = 100;

        foreach (Message m in MessageList)
        {
            if (m.Position.y >= lowPoint)
            {
                lowPoint = (int)m.Position.y + m.height + 5;
            }
        }

        Message msg = new Message(newMessage, new Vector2(-300, lowPoint), this, true, color, boldFont);
        MessageList.Add(msg);
    }

    public void AddMessage(string newMessage)
    {
        foreach (Message ms in MessageList)
        {
            if (ms.Text == newMessage)
            {
                // Don't flood the user with the same message!
                return;
            }
        }

        int lowPoint = 100;

        foreach (Message m in MessageList)
        {
            if (m.Position.y >= lowPoint)
            {
                lowPoint = (int)m.Position.y + m.height + 5;
            }
        }

        Message msg = new Message(newMessage, new Vector2(-300, lowPoint), this);
        MessageList.Add(msg);
    }

    void Update()
    {
        foreach (Message m in toRemove)
        {
            MessageList.Remove(m);
        }
        foreach (Message msg in MessageList)
        {
            msg.Update();
        }
    }

    void OnGUI()
    {
        foreach (Message msg in MessageList)
        {
            msg.Draw();
        }
    }

    public void Remove(Message msg)
    {
        toRemove.Add(msg);
    }
}

public class Message
{
    public string Text;
    public Vector2 Position;
    public Messages Parent;
    public int height;

    GUIStyle s = new GUIStyle();
    RectOffset ro = new RectOffset();

    int state = 0;
    int TTX = 3;

    float timer = 0;

    public Message(string msg, Vector2 pos, Messages parent)
    {
        ro.bottom = 10;
        ro.left = 18;
        ro.top = 10;
        ro.right = 10;
        s.padding = ro;
        s.normal.textColor = Color.white;
        s.normal.background = parent.Background;
        s.wordWrap = true;
        s.stretchHeight = true;
        s.clipping = TextClipping.Overflow;

        Text = msg;
        Position = pos;
        Parent = parent;

        height = (int)s.CalcHeight(new GUIContent(Text), 300);
    }

    public Message(string msg, Vector2 pos, Messages parent, bool BigLetters, Color theColor, Font theFont)
    {
        ro.bottom = 10;
        ro.left = 22;
        ro.top = 7;
        ro.right = 10;
        s.padding = ro;
        s.normal.textColor = theColor;
        s.normal.background = parent.Background;
        s.font = theFont;
        s.wordWrap = true;
        s.stretchHeight = true;
        s.clipping = TextClipping.Overflow;

        Text = msg;
        Position = pos;
        Parent = parent;

        height = (int)s.CalcHeight(new GUIContent(Text), 300);
    }

    public void Draw()
    {
        GUI.Label(new Rect(Position.x, Position.y, 300, height), Text, s);
    }

    public void Update()
    {
        if (state == 0)
        {
            Position.x += 2000 * Time.deltaTime;
            if (Position.x >= Screen.width / 2 - 150)
            {
                Position.x = Screen.width / 2 - 150;
                state = 1;
            }
        }
        if (state == 1)
        {
            timer += Time.deltaTime;
            if (timer >= TTX)
            {
                state = 2;
            }
        }
        if (state == 2)
        {
            Position.x += 2000 * Time.deltaTime;
            if (Position.x > Screen.width)
            {
                Parent.Remove(this);
            }
        }
    }
}

Right, I will analyze this and see what I can do, I will report back to the same thread with my updates. Again, I will not copy and paste your code.

using: List<Message> does not work even with using Systems.Collections.Generic;

Clearly you forgot to implement the second class in the file called "Message".

I thought that was a type..Sorry...Im trying to see if using GUIText as the type to replace messages will work.

No, it won't. There are, quite obviously, custom updates and methods in the Message class which create the proper on-screen labels, and also enable some fly-in effects. You can't just replace an arbitrary Unity type with something that's been custom-coded.

GUI.Label supports multi-line text. You can position the text within a rectangle. Use a GUIStyle to control text justification, text wrap/clip, font, etc. This way your message list class could simply keep track of the text strings, then you draw all the messages at once as a single object, rather than worrying about stacking a bunch of GUI objects.

+1 simple efficient solution

There is a very good message ticker that works just like what you're describing here on the unify community, but it uses a guitext object in the scene, if you're cool with that.

http://www.unifycommunity.com/wiki/index.php?title=MessageDisplayer

I appreciate your response and the link. Thanks.

cool, thanks, I was thinking of writing something like that, now I don't have to!