- Home /
RemoveAt() not working within for() loop.
I am spawning trees in random locations around my landscape mesh. My code essentially locates all vertices on the landscape mesh, keeps only the vertices that would be good tree locations (based on criteria I've set), and saves these vertices in a list called "treeSpawnLocations". It then determines how many trees to spawn, based on a predetermined "treeDensity" float, and it uses a for() loop to instantiate each tree at a valid tree location (a random "treeType" from an array of tree prefabs, and at a random y rotation).
Here's where my problem is. I don't want multiple trees spawning at the same location. So after each tree spawns, within the for() loop, I use treeSpawnLocations.RemoveAt(t) to remove that spawn point from the list of possible spawn locations. The code works perfectly except that multiple trees still spawn at the same locations. The code seems to completely ignore that line. Any idea why?
TLDR: I'm trying to remove an item from a list in each for() loop so that item doesn't get pulled again in the next loop, but it doesn't get removed.
Here's the section of code relevant to my question:
int treesToSpawn = Mathf.RoundToInt(treeSpawnLocations.Count * treeDensity);
for (int i = 0; i < treesToSpawn; i++)
{
int t = Random.Range(0, treeSpawnLocations.Count - 1);
Instantiate(treeTypes[Random.Range(0, treeTypes.Length - 1)], treeSpawnLocations[t], Quaternion.Euler(Quaternion.identity.x, Random.Range(0, 360), Quaternion.identity.z));
treeSpawnLocations.RemoveAt(t);
}
Answer by andrew-lukasik · Apr 13, 2021 at 06:31 AM
RemoveAt
works fine. Your treeSpawnLocations
contains duplicate entries.
void RemoveDuplicates ( List<Vector3> list )
{
var set = new HashSet<Vector3>( list );
list.Clear();
list.AddRange( set );
}
Wow, you're right! I looked back at my code and realized that yep, there are some instances when a vertex could be listed twice. I guess I overlooked that. Now I just have to figure out the most performant way to either prevent duplicates from occurring or to remove all duplicates at the same time after instantiating the tree. I could use another for() loop to remove all duplicates, but that would add another ~800,000 loops at the start of my game... I'll have to get creative. Thanks for your help.
HashSet
is a reasonable option here because it's Add
/Push
is O(1) operation and not O(n) (repeated iteration over long collection is a big no-no, performance wise). I suggest you use HashSet<Vector3>
when assembling that list and convert it to List<Vector3>
when it's done.
Your answer
Follow this Question
Related Questions
A node in a childnode? 1 Answer
List That Won't Remove The Last Two Elements 3 Answers
how do I remove a class item from a list? 1 Answer
Using for loop to gather all waypoint objects near player 2 Answers
Remove all duplicates from a list 1 Answer