Generating Walls During Runtime

Hi, I’m fairly new to Unity. I haven’t made anything that anyone could call a game, right now I’m just trying different things out seeing how they work. I’m thinking I’m about ready to make my first ‘game’.

The concept is very simple, it will be a randomly generated maze that the player has to navigate (first person) to get to the exit point, moving on to the next level.

I’m thinking that a good starting point would be the level generation. I am wondering what the best approach would be.

This is my thought process so far:

  • Have a plane for the floor, manually setting the Y location so that my wall prefabs fit nicely when they have a y position of 0
  • Since there would be no movement on the Y axis all I’m concerned with the X and Z locations of the walls.
  • I thought it would be nice to have thin walls but after considering it, I think it may be easier to have the ‘walls’ fill a whole cell.
  • I want the maze to be scalable starting small and getting larger. 100x100 at the maximum (this may be too large to be practical, but just throwing that out there as a hard max).
  • Using a cube as the wall object, I generated a 100x100 grid filled with 1x1x1 cubes. I noticed a significant performance hit (obviously that is a lot of objects).
  • I thought about scaling the cubes to reduce the number of objects loaded into the scene (ex: 4 walls in a row along the x axis would be 1 cube scaled out 4, instead of 4 individual cubes). I ran into some positioning problems.

Anyway the point of this thread is to ask what any of you guys would suggest in so far as building these walls. What would be the most inexpensive way to achieve what I’m looking for?

It would be best to use the Mesh class to construct meshes. Create the maze in an array, and use the array to construct the mesh (and the array can also be used for collision detection, that way you avoid mesh colliders). It’s best to do it in chunks; aside from a vertex limit per-mesh, using chunks allows you do make a custom occlusion culling routine, in which case doing 10,000 x 10,000 would be feasible. See here and here for some more relevant info.

–Eric

Thanks Eric, how would one use the array for collisions?

EDIT:
I looked at the second link there about the FPS in grid motion. My goal is to move in a standard FPS way, I’m not really looking for the grid based movement. So would that mean that my array couldn’t be used for collisions?

You could, but it would be harder. Probably best to use mesh colliders in this case.

–Eric

Obviously I don’t know how to use the UVs could someone help me out?

  void RenderCell(Cell c, Vector3[] verts, int[] tris, Vector2[] uvs)
    {
        int x = c.x;
        int y = c.y;
        

        
        //floor
        verts[vIndex++] = new Vector3(0+x, 0, 0-y);
        verts[vIndex++] = new Vector3(0+x, 0, 1-y);
        verts[vIndex++] = new Vector3(1+x, 0, 1-y);
        verts[vIndex++] = new Vector3(1+x, 0, 0-y);

        uvs[uIndex++] = new Vector2(0f, 0f);
        uvs[uIndex++] = new Vector2(0f, 1f);
        uvs[uIndex++] = new Vector2(1f, 1f);
        uvs[uIndex++] = new Vector2(1f, 0f);

        tris[tIndex++] = vIndex - 4;
        tris[tIndex++] = vIndex - 3;
        tris[tIndex++] = vIndex - 2;
        tris[tIndex++] = vIndex - 2;
        tris[tIndex++] = vIndex - 3;
        tris[tIndex++] = vIndex - 4;

        tris[tIndex++] = vIndex - 4;
        tris[tIndex++] = vIndex - 1;
        tris[tIndex++] = vIndex - 2;
        tris[tIndex++] = vIndex - 2;
        tris[tIndex++] = vIndex - 1;
        tris[tIndex++] = vIndex - 4;

        if (c.CheckWall(Direction.North))
        {
            verts[vIndex++] = new Vector3(0+x, 0, 1-y);
            verts[vIndex++] = new Vector3(0+x, 2, 1-y);
            verts[vIndex++] = new Vector3(1+x, 2, 1-y);
            verts[vIndex++] = new Vector3(1+x, 0, 1-y);

            uvs[uIndex++] = new Vector2(0f, 0f);
            uvs[uIndex++] = new Vector2(0f, 1f);
            uvs[uIndex++] = new Vector2(1f, 1f);
            uvs[uIndex++] = new Vector2(1f, 0f);

            tris[tIndex++] = vIndex - 4;
            tris[tIndex++] = vIndex - 3;
            tris[tIndex++] = vIndex - 2;
            tris[tIndex++] = vIndex - 2;
            tris[tIndex++] = vIndex - 3;
            tris[tIndex++] = vIndex - 4;

            tris[tIndex++] = vIndex - 4;
            tris[tIndex++] = vIndex - 1;
            tris[tIndex++] = vIndex - 2;
            tris[tIndex++] = vIndex - 2;
            tris[tIndex++] = vIndex - 1;
            tris[tIndex++] = vIndex - 4;

            

        }
        if (c.CheckWall(Direction.East))
        {

            verts[vIndex++] = new Vector3(1+x, 0, 0-y);
            verts[vIndex++] = new Vector3(1+x, 2, 0-y);
            verts[vIndex++] = new Vector3(1+x, 2, 1-y);
            verts[vIndex++] = new Vector3(1+x, 0, 1-y);

            uvs[uIndex++] = new Vector2(0f, 0f);
            uvs[uIndex++] = new Vector2(0f, 1f);
            uvs[uIndex++] = new Vector2(1f, 1f);
            uvs[uIndex++] = new Vector2(1f, 0f);

            tris[tIndex++] = vIndex - 4;
            tris[tIndex++] = vIndex - 3;
            tris[tIndex++] = vIndex - 2;
            tris[tIndex++] = vIndex - 2;
            tris[tIndex++] = vIndex - 3;
            tris[tIndex++] = vIndex - 4;

            tris[tIndex++] = vIndex - 4;
            tris[tIndex++] = vIndex - 1;
            tris[tIndex++] = vIndex - 2;
            tris[tIndex++] = vIndex - 2;
            tris[tIndex++] = vIndex - 1;
            tris[tIndex++] = vIndex - 4;

        }

        if (c.CheckWall(Direction.South))
        {
            
            verts[vIndex++] = new Vector3(0+x, 0, 0-y);
            verts[vIndex++] = new Vector3(0+x, 2, 0-y);
            verts[vIndex++] = new Vector3(1+x, 2, 0-y);
            verts[vIndex++] = new Vector3(1+x, 0, 0-y);

            uvs[uIndex++] = new Vector2(0f, 0f);
            uvs[uIndex++] = new Vector2(0f, 1f);
            uvs[uIndex++] = new Vector2(1f, 1f);
            uvs[uIndex++] = new Vector2(1f, 0f);

            tris[tIndex++] = vIndex - 4;
            tris[tIndex++] = vIndex - 3;
            tris[tIndex++] = vIndex - 2;
            tris[tIndex++] = vIndex - 2;
            tris[tIndex++] = vIndex - 3;
            tris[tIndex++] = vIndex - 4;

            tris[tIndex++] = vIndex - 4;
            tris[tIndex++] = vIndex - 1;
            tris[tIndex++] = vIndex - 2;
            tris[tIndex++] = vIndex - 2;
            tris[tIndex++] = vIndex - 1;
            tris[tIndex++] = vIndex - 4;

        }
        if (c.CheckWall(Direction.West))
        {

            verts[vIndex++] = new Vector3(0+x, 0, 0-y);
            verts[vIndex++] = new Vector3(0+x, 2, 0-y);
            verts[vIndex++] = new Vector3(0+x, 2, 1-y);
            verts[vIndex++] = new Vector3(0+x, 0, 1-y);

            uvs[uIndex++] = new Vector2(0f, 0f);
            uvs[uIndex++] = new Vector2(0f, 1f);
            uvs[uIndex++] = new Vector2(1f, 1f);
            uvs[uIndex++] = new Vector2(1f, 0f);

            tris[tIndex++] = vIndex - 4;
            tris[tIndex++] = vIndex - 3;
            tris[tIndex++] = vIndex - 2;
            tris[tIndex++] = vIndex - 2;
            tris[tIndex++] = vIndex - 3;
            tris[tIndex++] = vIndex - 4;

            tris[tIndex++] = vIndex - 4;
            tris[tIndex++] = vIndex - 1;
            tris[tIndex++] = vIndex - 2;
            tris[tIndex++] = vIndex - 2;
            tris[tIndex++] = vIndex - 1;
            tris[tIndex++] = vIndex - 4;

        }
    }