- Home /
Changing a string in a loop each second
Hi!
I want to make a "connecting box" where it shows that it is connecting. Just to make it a bit fancier, I want my three last dots to appear and disappear. I made this IEnumarator to make a while loop. I honestly don't know how to make loops with WaitForSeconds so if you could help me, it would be very appreciated!
My code:
void Start () {
StartCoroutine (ConnectingStringUpdater ());
}
IEnumerator ConnectingStringUpdater () {
while (connecting == true) {
connectingString = "Connecting";
yield return new WaitForSeconds(1);
connectingString = "Connecting.";
yield return new WaitForSeconds(1);
connectingString = "Connecting..";
yield return new WaitForSeconds(1);
connectingString = "Connecting...";
yield return new WaitForSeconds(1);
}
}
Thanks
Answer by lukos · Jun 21, 2014 at 05:32 PM
Hi, Try this, is cleaner:
public bool connecting;
public string connectingString;
void Start ()
{
connectingString = "Connecting";
StartCoroutine (ConnectingStringUpdater ());
}
IEnumerator ConnectingStringUpdater ()
{
while (connecting == true) {
if (connectingString.Substring(connectingString.Length-3) != "...") connectingString += ".";
else connectingString = "Connecting";
yield return new WaitForSeconds(1);
}
}
Answer by angarg12 · Jun 23, 2014 at 02:11 PM
Your solution works, but it is ugly because you repeat a lot of code. It is good that you are trying to improve it!.
Whenever you find yourself repeating too much code, think if you can make it a loop. You an outer loop, but you can also make the inside into a loop. Also, it is possible that this solution has poor performance, although it is possible that the compiler optimization takes care of that.
You can put your labels in an array and then circularly walk the array. The resulting code would look something like this (notice that it is also good practice to put "magic numbers" in descriptive variables).
string displayLabel;
string[] connectingLabels;
bool connecting = true;
public static readonly float LABEL_UPDATE_DELAY = 1f;
void Start () {
connectingLabels = new string[4];
connectingLabels[0] = "Connecting";
connectingLabels[1] = "Connecting.";
connectingLabels[2] = "Connecting..";
connectingLabels[3] = "Connecting...";
displayLabel = connectingLabels [0];
StartCoroutine (ConnectingStringUpdater ());
}
void OnGUI () {
GUILayout.Label(displayLabel);
}
IEnumerator ConnectingStringUpdater () {
int currentIndex = 0;
while (connecting == true) {
displayLabel = connectingLabels [currentIndex];
yield return new WaitForSeconds(LABEL_UPDATE_DELAY);
currentIndex = (currentIndex+1)%connectingLabels.Length;
}
}
Of course this code itself has some issues. You are fiddling around with the array index, which isn't a very good idea. Also your intention doesn't seems too clear from the code.
Can you do better? Of course! Since you are walking an array circularly, you might as well use a data structure made for that. In the next example we suppose you have a class CircularList. There are many implementations available on the internet if you don't feel like making your own (and you shouldn't).
Node displayLabel;
CircularList connectingLabels;
bool connecting = true;
public static readonly float LABEL_UPDATE_DELAY = 1f;
void Start () {
connectingLabels = new CircularList();
connectingLabels.add("Connecting");
connectingLabels.add("Connecting.";
connectingLabels.add("Connecting..");
connectingLabels.add("Connecting...");
displayLabel = connectingLabels.head();
StartCoroutine (ConnectingStringUpdater ());
}
void OnGUI () {
GUILayout.Label(displayLabel.value());
}
IEnumerator ConnectingStringUpdater () {
while (connecting == true) {
yield return new WaitForSeconds(LABEL_UPDATE_DELAY);
displayLabel = displayLabel.next();
}
}
I haven't checked this code, but it should give you an idea on how to implement it with a CircularList. The advantages of this solution is that you don't have to care about indexes at all, and your intent is much clearer from the code.
Answer by Jeff-Kesselman · Jun 23, 2014 at 02:20 PM
Of course you could do it even simpler...
Node displayLabel;
int dotCount=0;
bool connecting = true;
public static readonly float LABEL_UPDATE_DELAY = 1f;
void Start () {
displayLabel = "Connecting";
StartCoroutine (ConnectingStringUpdater ());
}
void OnGUI () {
GUILayout.Label(displayLabel.value());
}
IEnumerator ConnectingStringUpdater () {
while (connecting == true) {
yield return new WaitForSeconds(LABEL_UPDATE_DELAY);
displayLabel = "Connecting";
for(int i=0;i<dotCount%4;i++){
displayLabel+=".";
}
dotCount++;
}
}
Well, the whole point of making the code like that is to make it clear, not obscure. Also works in the general case, if you want to cycle through different messages and not only add dots.
There is also the performance issue, concatenating strings is expensive, although as I said maybe the compiler optimizes it and isn't such a big deal.
Your answer
Follow this Question
Related Questions
Using Loops 1 Answer
What part of my While Loop is causing the game to freeze? (C#) 2 Answers
while loop & array- turn on something via percentage 1 Answer
Problem with while loop in Coroutine 2 Answers
Breaking from a Loop 2 Answers