- 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