- Home /
How to put a list of strings in a Text Unity 4.6 UI element
So i have this GUI.Label that has a list of strings to make my chat, but it doesn't work when i try it with an Unity 4.6 Text UI element.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class ChatManager : MonoBehaviour {
public static bool isChatOpen;
List<string> chatEvents;
int maxMessagesOnChat = 10;
void Start ()
{
chatEvents = new List<string>();
}
public void AddChatEvent(string evt)
{
GetComponent<PhotonView>().RPC("AddChatEvent_RPC", PhotonTargets.All, evt);
}
[RPC]
void AddChatEvent_RPC(string evt)
{
while(chatEvents.Count >= maxMessagesOnChat)
{
chatEvents.RemoveAt(0);
}
chatEvents.Add(evt);
}
void OnGUI()
{
GUI.contentColor = Color.black;
GUILayout.BeginArea(new Rect(0, 0, Screen.width, Screen.height));
GUILayout.BeginVertical();
GUILayout.FlexibleSpace();
foreach(string msg in chatEvents)
{
GUILayout.Label(msg);
}
GUILayout.FlexibleSpace();
GUILayout.EndVertical ();
GUILayout.EndArea();
}
}
where's your code for the new UI? OnGUI()
is the legacy stuff...
So i tried it like this but it didn't show a list of messages it showed only the latest message in the list
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
public class Chat$$anonymous$$anager : $$anonymous$$onoBehaviour {
public static bool isChatOpen;
List<string> chatEvents;
int max$$anonymous$$essagesOnChat = 10;
void Start ()
{
chatEvents = new List<string>();
}
public void AddChatEvent(string evt)
{
GetComponent<PhotonView>().RPC("AddChatEvent_RPC", PhotonTargets.All, evt);
}
[RPC]
void AddChatEvent_RPC(string evt)
{
while(chatEvents.Count >= max$$anonymous$$essagesOnChat)
{
chatEvents.RemoveAt(0);
}
chatEvents.Add(evt);
}
void Update()
{
foreach(string msg in chatEvents)
{
ChatLabel$$anonymous$$anager.chatLabel.text = msg;
}
}
}
Answer by Mmmpies · Dec 09, 2014 at 12:02 PM
gjf is right, nothing in your script refferences the new GUI elements. Have a look here:
YouTube Search for unity 4.6 ui
EDIT:
That's more like it :¬) I think your code is working. It's even likely it's displaying all messages just really really fast.
What you're doing is asking the text to change to the next bit of text in your array overwritting the previous.
If you want it all to appear instantly you'll need to set a string variable and add each line. I'm not near a computer with unity right now so can't test this but:
private String myString;
then in your foreach...
myString = mySting.ToString() + msg.ToString() + "\n";
once the loop finishes
ChatLabelManager.chatLabel.text = myString;
Like I said I can't test it and you might not need the ToString() as I'm working from memory.
If you want the messages to appear one after another time wise you'll need to set some delay, but not much point speculating on how you want it to display as it could be anyway.
Oh and the n should be backslash n but backslash seem to vanish.
EDIT 2:
Try
private String display = "";
Not easy working on this without Unity to check I'm not giving you bad info but I think it's just not happy with display being null.
EDIT 3:
Well the good news is I now have access to Unity, give me a couple of minutes and I'll see if I can work out what's going on. Has the Null Reference been fixed though?
Oh and is that message the last one in your array?
Finally can you post the latest code so we both have the same code to look at?
Thanks
EDIT 4:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
public class DisplayText : MonoBehaviour {
public Canvas myCanvas;
public Text myText;
private string display = "";
List<string> chatEvents;
private bool callMe;
// Use this for initialization
void Start () {
chatEvents = new List<string>();
chatEvents.Add("this ");
chatEvents.Add (" is ");
chatEvents.Add (" a ");
chatEvents.Add (" test ");
chatEvents.Add (" for ");
chatEvents.Add (" concatenating ");
chatEvents.Add (" strings ");
chatEvents.Add (" and ");
chatEvents.Add (" displaying ");
chatEvents.Add(" on ");
chatEvents.Add(" the ");
chatEvents.Add (" new ");
chatEvents.Add (" GUI");
callMe = true;
}
// Update is called once per frame
void Update () {
if(callMe)
{
AddText();
callMe = false;
}
}
void AddText()
{
foreach(string msg in chatEvents)
{
display = display.ToString () + msg.ToString() + "\n";
}
myText.text = display;
}
}
This works for me, one of the issues is you've got the code in Update so it keeps doing it over and over. I took my code out of the update and forced up date to only call it once.
EDIT 5:
If you use one text area then you'll get the full list of all messages. If you only want to show the 5 most recent then setup a panel on the canvas with 5 text areas.
When you get the 1st message put it in the first area. Then the second message in the second text area and on until all 5 are full.
When the next message arrives move the text in 2 to 1, 3 too 2, 4 to 3 and 5 to 4. Then put the new message in 5.
I hope that makes sense as I'm again away from a computer with Unity.
EDIT 6:
Well this is embarrassing! Can I work out how to do the smooth transitions on the new GUI. I'll answer that myself, and the answer is no.
Well this is far more basic than intended but it works bar the logic of showing the last entry. That shouldn't affect you as you'll be calling it in a different way.
Basically it has 5 numbered "Buttons" empty gameObjects that are simply place holders.
Then we instantiate a prefab and set the transform to the first then second and so on. If the counter myNumber gets to 6 or more it moves the transform for each object and removes the lowest.
It works by holding a script on the prefab that just holds the prefab number and aligns it with the Button number.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
public class DisplayText : MonoBehaviour {
public Canvas myCanvas;
private GameObject myGo;
private Text myText;
public GameObject TextPrefab;
private GameObject curText;
private int messageNumber = 0;
private string display = "";
private string goString;
List<string> chatEvents;
private bool callMe;
private float lastMessageTime;
private float newMessageTime;
private GameObject destination;
public GameObject myPanel;
// Use this for initialization
void Start () {
chatEvents = new List<string>();
chatEvents.Add("this ");
chatEvents.Add ("is ");
chatEvents.Add ("a ");
chatEvents.Add ("test ");
chatEvents.Add ("for ");
chatEvents.Add ("concatenating ");
chatEvents.Add ("strings ");
chatEvents.Add ("and ");
chatEvents.Add ("displaying ");
chatEvents.Add("on ");
chatEvents.Add("the ");
chatEvents.Add ("new ");
chatEvents.Add ("GUI");
callMe = true;
}
// Update is called once per frame
void Update () {
if(callMe)
{
messageNumber = messageNumber + 1;
if((messageNumber - 1)<= chatEvents.Count)
{
AddText(messageNumber);
callMe = false;
lastMessageTime = Time.time;
newMessageTime = Random.Range(1,4);
}
}
if(Time.time > lastMessageTime + newMessageTime)
{
if(messageNumber <= chatEvents.Count - 2)
{
Debug.Log(messageNumber + " " + chatEvents.Count);
callMe = true;
}
}
}
void AddText(int myNumber)
{
display = chatEvents[myNumber];
if (myNumber < 6)
{
goString = "Button" + myNumber.ToString();
//Debug.Log (goString);
curText = GameObject.Find (goString);
myGo = (GameObject)Instantiate (TextPrefab);
myGo.transform.SetParent (myPanel.transform);
myGo.transform.position = curText.transform.position;
myGo.GetComponent<MyNumber>().MyNo = myNumber;
}
else
{
for (int i = 1; i <= 5; i++)
{
if (i == 1)
{
destination = GameObject.Find ("ButtonDead");
GameObject[] argo = GameObject.FindGameObjectsWithTag("TextPrefab");
foreach (GameObject go in argo)
{
if(go.GetComponent<MyNumber>().MyNo == 1)
{
myGo = go;
myText = myGo.GetComponent<Text>();
myText.GetComponent<MyNumber>().MyNo = (i - 1);
Destroy(myGo);
}
}
}
if (i > 1)
{
GameObject[] argo = GameObject.FindGameObjectsWithTag("TextPrefab");
foreach (GameObject go in argo) {
if(go.GetComponent<MyNumber>().MyNo == i)
{
myGo = go;
myText = myGo.GetComponent<Text>();
Debug.Log (" myText = " + myText.text);
goString = "Button" + (i - 1);
destination = GameObject.Find (goString);
myText.GetComponent<MyNumber>().MyNo = (i - 1);
myText.transform.position = destination.transform.position;
}
}
}
if(i == 5)
{
curText = GameObject.Find ("Button5");
myGo = (GameObject)Instantiate (TextPrefab);
//myGo.transform.SetParent = curText.transform;
myGo.transform.SetParent (myPanel.transform);
myGo.transform.position = curText.transform.position;
myGo.GetComponent<MyNumber>().MyNo = 5;
}
}
}
display = chatEvents[(myNumber - 1)];
myText = myGo.GetComponent<Text>();
myText.text = display;
}
}
And this is a link to the package so you can see what's going on:
But as with everything web based virus scan file on download, didn't have a virus when it left me but once on the web who knows.
Ok i tried your answer:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
public class Chat$$anonymous$$anager : $$anonymous$$onoBehaviour {
public static bool isChatOpen;
List<string> chatEvents;
int max$$anonymous$$essagesOnChat = 10;
private string display;
void Start ()
{
chatEvents = new List<string>();
}
public void AddChatEvent(string evt)
{
GetComponent<PhotonView>().RPC("AddChatEvent_RPC", PhotonTargets.All, evt);
}
[RPC]
void AddChatEvent_RPC(string evt)
{
while(chatEvents.Count >= max$$anonymous$$essagesOnChat)
{
chatEvents.RemoveAt(0);
}
chatEvents.Add(evt);
}
void Update()
{
foreach(string msg in chatEvents)
{
display = display.ToString() + msg.ToString() + "n";
ChatLabel$$anonymous$$anager.chatLabel.text = display;
}
}
}
But it gave me an error:NullReferenceException: Object reference not set to an instance of an object Chat$$anonymous$$anager.Update () (at Assets/Scripts/Chat$$anonymous$$anager.cs:36)
That kind of works but it doesn't still show properly... When i add a new message it does show the old messages again for some reason.
Code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
public class Chat$$anonymous$$anager : $$anonymous$$onoBehaviour {
public static bool isChatOpen;
List<string> chatEvents;
int max$$anonymous$$essagesOnChat = 10;
private string display = "";
private bool newEvent = false;
private
void Start ()
{
chatEvents = new List<string>();
}
public void AddChatEvent(string evt)
{
GetComponent<PhotonView>().RPC("AddChatEvent_RPC", PhotonTargets.All, evt);
newEvent = true;
}
[RPC]
void AddChatEvent_RPC(string evt)
{
while(chatEvents.Count >= max$$anonymous$$essagesOnChat)
{
chatEvents.RemoveAt(0);
}
chatEvents.Add(evt);
}
void Update()
{
if(newEvent == true)
{
UpdateChat();
newEvent = false;
}
}
void UpdateChat()
{
foreach(string msg in chatEvents)
{
display = display.ToString() + msg.ToString() + "\n";
ChatLabel$$anonymous$$anager.chatLabel.text = display;
}
}
}
Screenshot:
Now I've got access to Unity for a couple of hours (before bed anyway!). There are lots of ways of achieving the kind of thing you want but the method you want to use will dictate how the text appears.
Any method I'd recommend using the new GUI because it's faster and far more professional.
So what do you want to do with your text? Do you want to be able to scroll back through all items or just have 5 (or any other number) on screen at any one time? Do you want the text just to pop into place and move the previous messages upwards as I suggested? Or do you want fancy pants text scrolling smoothly up with the earliest message fading out whilst the latest message flashes into place with a subtle combination of color and size changes?
There are some fairly easy ways to implement any of these but depending what you want you'd have to take a different approach to the setup.
To scroll back through all time you'd need a scroll panel, for the method I mentioned earlier for 5 messages you just need 5 Text components stacked on top of one another like floors in a skyscraper. For the fancy pants you'd create a new Text object for the bottom most and alter the RectTransform of the buttons above so they scroll upwards. Fading out the top one then destroying it.
Really if you're still having trouble let me know how you want your text to appear/vanish and what lifespan you need (for the text - not you!) and I'll try to find a workable solution.
If you think you're O$$anonymous$$ just mark this as answered. I'd still get email updates if you marked it as answered and then updated if you run into trouble.
Answer by Kiwasi · Dec 13, 2014 at 07:15 AM
Nice to see one of my tutorials made it to the front page of the search list! You can probably adapt my dynamic drop down menu for this purpose
For a scrolling set up I would suggest the following.
Create a canvas
Add a panel. Size the panel to match the size of your message display. Add a mask component.
Make a child panel. Set it as the content of your mask above. Add a scroll rect. Add sliders if you want them. Add a content fitter and a vertical layout group
Make a child text element. Add a layout group and size as you see fit. Make this a prefab, and delete it from the scene. (Sometimes it makes sense to give this element a panel and so forth as well).
As each message comes in Intantiate a prefab via script. Set its parent to the panel object above. The scrollrect, mask and layout elements will take care of everything else for you.
Sorry, but i think i am gonna go with the legacy gui... Cause this is just too much work
O$$anonymous$$ @D$$anonymous$$-Games, I'm going to post a script later to show you how to do this on the new GUI, some of it ties in with what I'll need anyway so I might as well post it. Just gonna take an hour or so.
Unity should probably implement an chat component to their new gui system
@D$$anonymous$$-Games You are not likely to see a Unity implemented chat components. A chat system can be implemented too many different ways for Unity to try make a single component. But you may see various chat systems turn up on the asset store.
Answer by TooManySugar · Jun 06, 2016 at 05:11 AM
I recognize the code from Quili18 from the PUN FPS tutorial in the second post by OP. I'had the same need to convert the console text to ui 4.6. This works for me: Youcan test by adding a chat entry on keypress.
The _UIM is a call to a static script tha holds the ui text object.
variables:
List <string> chatMessages;
int maxChatMessages = 5;
private string ChatLine;
public void AddChatMessage (string m) {
transform.GetComponent<PhotonView>().RPC ("AddChatMessage_RPC",PhotonTargets.All,m);
//Component comp = overlayComponent;
}
[PunRPC]
void AddChatMessage_RPC (string m) {
while (chatMessages.Count >=maxChatMessages){//while there are more messages than we want remove oldest entry
chatMessages.RemoveAt (0);
_UIM.ui_Online_Console_text.GetComponent<Text>().text ="";//reset the printed text
}
chatMessages.Add (m);
foreach(string msg in chatMessages) {//we print the text
ChatLine = msg.ToString () + '\n';
_UIM.ui_Online_Console_text.GetComponent<Text>().text += ChatLine;
}
Just curious, what did you put in the _UI$$anonymous$$ script? I'm trying what you put with some alteration to fit the missing script but without that script I keep running into an issue where messages repeat every time I press the send button.
Your answer
Follow this Question
Related Questions
A node in a childnode? 1 Answer
Update List<> in editor 0 Answers
Is it possible to name a list by a string variable? 2 Answers
How do I make a list of lists? 2 Answers
Cannot convert string to int. 1 Answer