Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by PippyLongbeard · Feb 03, 2015 at 08:07 AM · c#listfor-loopremoveelement

List That Won't Remove The Last Two Elements

Alright, so I'm setting up a little subtitle GUI for a project, and I'm doing this by building a list of strings (the words), then feeding them to a Text GUI in 16 word segments.

Relevant Code:

 int wordsDisplayed = 16;
 //All of the following is inside an IEnumerator named 'Delay'
 if (list.Count > 0)
 {
     Debug.Log (list.Count);
     text.GetComponent<Text> ().text = "";
 
     if(list.Count >= wordsDisplayed)
     {
         for(int i = 0; i < wordsDisplayed; i++)
         {
             if(list[i]!=null)
             {
                 text.GetComponent<Text> ().text += list[i];
                 list[i] = null;
             }
         }
     }
     else
     {
         for(int i = 0; i < list.Count - 1; i++)
         {
             if(list[i]!=null)
             {
                 text.GetComponent<Text> ().text += list[i];
                 list[i] = null;
             }
         }
     }
 
     for(int i = list.Count - 1; i > 0; i--)
     {
         if(list[i]==null)
         {
             list.RemoveAt (i);
         }
     }
 
     StartCoroutine(Delay (time, list));
 }
 //If list is empty, aka all words have been displayed, end the dialogue state
 else
 {
     //End dialogue
 }

The problem is that the Debug.Log() on line 5 is saying that the count of list is, starting from the first loop: 100, 84, 68, 52, 36, 20, 4, 2, 2, 2, etc... I can't figure out why is won't go ahead an remove the last two elements from the list. They're displayed just fine on the actual Text GUI component, they just won't remove themselves from the list. Any ideas on what's going on? Thanks in advance.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

3 Replies

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by Gizmoi · Feb 03, 2015 at 08:13 AM

In the 2nd loop, your loop condition is i < list.Count - 1 meaning it will never check the last element and set it to null. In the final loop your condition is i > 0 meaning it will never check the first element in the array.

I'm assuming the first and last elements are the 2 remaining in your list.

Change the 2nd loop's condition to i < list.Count and change the final loop's condition to i >= 0

Edit: It's also probably better to simply do

 list.RemoveAt(i);
 i--;

when you want to remove an item from your list rather than setting it to null then checking it later.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image PippyLongbeard · Feb 03, 2015 at 08:29 AM 0
Share

well, that's weird. It looks like I was assu$$anonymous$$g that the for loop would keep running one more time after its condition was considered false. I don't know what I was thinking. Thanks for the answer. oh yeah, and there was a reason why I am not using removeat(). I can't remember why right now.

avatar image
2

Answer by daneislazy · Feb 03, 2015 at 10:19 AM

So, I realize that your issue has already been resolved, but I wanted to jump in to clear up a few things. First off for those still wondering, you are replacing the list with nulls because you are iterating over it with 'i' and if you remove the item the script will start skipping items. Instead of iterating over it you could just use text.GetComponent().text += list[0]; list.RemoveAt(0); then check to see if the list is empty and break out of the for loop. Also you could use a while or modify your for to accomplish the break as well.

Also of note is that you seem to be using coroutines... oddly. If all that code is in the Delay IEnumerator then you are Recursively calling Delay from within itself. You really don't need to do that. If you use a while loop and a yield return new waitforseconds(time); right before the end of the loop it will return and keep running after the set time without having to call it again.

It's probably best explained with actual code so here you go.

 int wordsToDisplay = 16;
 float textDelay = 10f;
 List<string> list = new List<string>();
 
 // or you can pass some/all into the IEnumerator, it will retain info between yields
 IEnumerator Delay() {
 // you could also grab the text component here so you are not doing it repeatedly
     while(list.Count > 0) {
         text.GetComponent<Text>().text = "";
         for(int i = 0;(list.Count > 0 && i < wordsToDisplay);i++) {
             text.GetComponent<Text>().text += list[0];
             list.RemoveAt(0);
         }
         yield return new WaitForSeconds(textDelay);
         // returns here after textDelay then rechecks the while loop
     }
 }

then you just have to set the list with the text and call StartCoroutine(delay());

Hope that helps clear things up, and I hope the code works (I didn't test it) or at least gets the idea across.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image PippyLongbeard · Feb 04, 2015 at 12:55 AM 0
Share

Wow. You just completely solved that annoying RemoveAt(i) problem. Damn, I looked on all sorts of boards (including this one) and the general consensus was to use a separate for loop to remove elements. Never thought to just pull out the first element every time. I try not to use while loops in Unity, because any time I screw up a single thing with the returns or conditions, then Unity will crash the second I test it. It just winds up being too much hassle. I really wish I could give you more up votes, that was very informative.

avatar image Gizmoi · Feb 04, 2015 at 07:12 AM 0
Share

In this instance a while loop is much more readable for what you're trying to achieve, however the general consensus for removing elements in a list you are iterating over is RemoveAt(I) and then decrement i :)

avatar image
0

Answer by NoseKills · Feb 03, 2015 at 08:16 AM

Few suspect thing in your code

          for(int i = 0; i < list.Count - 1; i++)
          {
              if(list[i]!=null)
              {
                  text.GetComponent<Text> ().text += list[i];
                  list[i] = null;
              }
          }

why aren't you adding and nulling the last item in the list. Looks like it might get left on the list. Should it be ?

 for(int i = 0; i < list.Count; i++)


And Here

      for(int i = list.Count - 1; i > 0; i--)
      {
          if(list[i]==null)
          {
              list.RemoveAt (i);
          }
      }
 

Same thing there. You don't do anything to the "0" index. You spot at index 1. Should it be ?

 for(int i = list.Count - 1; i >= 0; i--)
Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Gizmoi · Feb 03, 2015 at 08:18 AM 0
Share

Exactly what I said.

avatar image PippyLongbeard · Feb 03, 2015 at 08:31 AM 0
Share

thanks for taking the time to answer. I just chose the quickest answer.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

22 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

A node in a childnode? 1 Answer

Multiple Cars not working 1 Answer

Affect every object in array. 1 Answer

Distribute terrain in zones 3 Answers

Removing a class object from a list(.remove not working) C# 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges