- Home /
How to reference a multidimensional list?
I have been following a tutorial on creating a minecraft like world, but want to change an array to a list to allow for infinite generation.
I want to be able to pass a "chunks[x, y, z].Init" or something to that effect from the world but I'm struggling. using the array it works but when changing to either of the two lists I just cant get it to work. I have the following;
 using System.Linq;
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class World : MonoBehaviour
 {
     /*List<Chunk[,,]> chunks = new List<Chunk[,,]>();*/
     List<Chunk> chunks = new List<Chunk>();
     /*Chunk[,,] chunks = new Chunk[20, 20, 20];*/
     List<ChunkCoord> chunksToCreate = new List<ChunkCoord>();
     private bool isCreatingChunks;
     private void Start()
     {
         GenerateWorld();   
     }
     private void Update()
     {
         CreateChunks();
     }
     void GenerateWorld()
     {
         for (int x = 0; x < 2; x++)
         {
             for (int y = 0; y < 2; y++)
             {
                 for (int z = 0; z < 2; z++)
                 {
                     chunks.Add(new Chunk(new ChunkCoord(x, y, z), this, false));
                     chunksToCreate.Add(new ChunkCoord(x, y, z));
                 }
             }
         }
     }
     IEnumerator CreateChunks()
     {
         isCreatingChunks = true;
         while (chunksToCreate.Count > 0)
         {
             chunks.Init();
             chunksToCreate.RemoveAt(0);
             yield return null;
         }
         isCreatingChunks = false;
     }
 }
and
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class Chunk
 {
     public ChunkCoord coord;
     World world;
     GameObject chunkObject;
     public Chunk(ChunkCoord _coord, World _world, bool generateOnLoad)
     {
         coord = _coord;
         world = _world;
         if (generateOnLoad)
             Init();
     }
     public void Init()
     {
         chunkObject = new GameObject();
         chunkObject.transform.SetParent(world.transform);
         chunkObject.transform.position = new Vector3(coord.x * Settings.ChunkSize, coord.y * Settings.ChunkSize, coord.z * Settings.ChunkSize);
         chunkObject.name = coord.x + ", " + coord.y + ", " + coord.z;
         Debug.Log("Chunk: " + coord.x + ", " + coord.y + ", " + coord.z + " generated.");
     }
 }
 public class ChunkCoord
 {
     public int x;
     public int y;
     public int z;
     public ChunkCoord()
     {
         x = 0;
         y = 0;
         z = 0;
     }
     public ChunkCoord(int _x, int _y, int _z)
     {
         x = _x;
         y = _y;
         z = _z;
     }
     public bool Equals(ChunkCoord other)
     {
         if (other == null)
             return false;
         else if (other.x == x && other.y == y && other.z == z)
             return true;
         else
             return false;
     }
 }
Not really sure what you're trying to do, can you give more information?
Answer by alwayscodeangry · Feb 20, 2020 at 06:39 PM
I'd suggest using a nested List. It can be a little difficult to parse, but basically you want a List of Lists of Lists of Chunks. This will effectively give you a three dimensional List of Chunks and, if initialized correctly, it can be accessed using indices that line up with your Chunk's coord field.
 
The declaration would look like this:
 List<List<List<Chunk>>> chunks = new List<List<List<Chunk>>>();
 
And an individual element at coords (x, y, z) would be accessed like this:
 chunks[x][y][z].Init();
 
I've made a couple of changes to your World class to get rid of the redundant secondary list (just use nested foreach loops for initialization) and correctly implement the CreateChunks() coroutine; hopefully this should be more or less what you're looking for:
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class World : MonoBehaviour
 {
     private List<List<List<Chunk>>> chunks = new List<List<List<Chunk>>>();
 
     private bool isCreatingChunks = false;
 
     private void Start()
     {
         GenerateWorld();
     }
 
     private void Update()
     {
         if (!isCreatingChunks)
         {
             StartCoroutine(CreateChunks());
         }
     }
 
     void GenerateWorld()
     {
         for (int x = 0; x < 2; x++)
         {
             chunks.Add(new List<List<Chunk>>());
 
             for (int y = 0; y < 2; y++)
             {
                 chunks[x].Add(new List<Chunk>());
 
                 for (int z = 0; z < 2; z++)
                 {
                     chunks[x][y].Add(new Chunk(new ChunkCoord(x, y, z), this, false));
                 }
             }
         }
     }
 
     private IEnumerator CreateChunks()
     {
         isCreatingChunks = true;
         
         foreach (List<List<Chunk>> xChunks in chunks)
         {
             foreach (List<Chunk> yChunks in xChunks)
             {
                 foreach(Chunk chunk in yChunks)
                 {
                     chunk.Init();
 
                     yield return null;
                 }
             }
         }
     }
 }
But it doesn't really make sense to have a chunk on every coordinate. The idea of chunking is to have 1 chunk represent an entire area, so why would u need to keep chunks on a x,y,z level, when a single list of chunks would be enough? It's not clear what OP wants to do.
I'm storing the chunks at intervals of ChunkSize, currently about 19 while testing. Then a script fills each with a array of voxels using chunk size for a multidimensional array size. Honestly this is my first project so I'm struggling to even explain stuff. But the answer seems to fix my issue perfectly. I'm not at a pc atm but once I am I'll test and post a reply.
As I understood it the question was about creating and accessing a multidimensional List, not chunking.
Yeah, generating and storing the chunks in either a list or array based on a x,y,z. For me to access later. I already have code that populates said chunks. Sorry if its confusing I'm not sure on alot of the ter$$anonymous$$ology yet.
Finally got to the PC. This seems to work brilliantly and give me what i wanted. but due to something of my own fault, it wont work going forward for me. I'm trying to have infinite generation of chunks (hence the "redundant" list). and using a list I believe wont allow me to have negative values or values out of sequence. but, hey-ho, this answer defiantly answered what i asked and helped me learn about nested lists and adding too them. it also lead me too looking at dictionaries for a possible fix. thank you so much for your time!
A Dictionary is a great solution in that case. Best of luck to you :)
Your answer
 
 
             Follow this Question
Related Questions
JS: Access sections of an array, without activating the rest 2 Answers
A node in a childnode? 1 Answer
Can't Activate a GameObject from Array 1 Answer
Make the audio manager select from an array of sounds 1 Answer
C# Random String Array help 2 Answers
 koobas.hobune.stream
koobas.hobune.stream 
                       
                
                       
			     
			 
                