Create a level from a png

TL;DR I want to take the image below and turn it into a playable level.

I new to Unity (i wonder how many questions start off like that?!) and im creating a rope racing game (like so many before me).

I have quite a lot of the core down but im having issues when it comes to level generation, what i have been doing up until now is using a simple level editor i made on day one just arranging and scaling primitive objects and saving the positions to a JSON file then on loading a level im reading said JSON files and generating the level from that, it works quite well but it is slow to actually create the levels in the first place.

What id like to be able to do is import in image file and generate the level based on that. for example if i had this image:
67682-level-example.png
the black lines would become terrain. Ideally id like just anything that isnt transparent to become terrain but id be happy with just sticking to a single colour if needs be.

I had assumed that this would be pretty simple (how naive i am) but no matter what i try i just cant for the life of me get anything to work. Getting the image into unity as a sprite or setting it as a texture on a quad or similar is fine but getting a collier to apply to it in the correct way just doesnt seem to be possible unless im missing something obvious.

Does anyone know if this is possible, and if it is could anyone please set me on the right track cos im all out of ideas.

I dont really care if i have to use 2D or 3D as both would work fine for my purposes (currently im using 3D for depth but only moving on x and y, but i working examples in 2d for some of it too).

Thanks.

Matt.

With the Texture2D.GetPixel(int x, int y) function (documentation), you can make a loop for each pixel, and instantiate a prefab (cube with dimensions according to the pixel) at this position if the pixel
complies with a condition (texture2D.GetPixel(x,y).a == 0).

For better performances, you can gather all aligned walls into a single wall, like in the following code:

public Texture2D tex;
public Texture2D cube;
void load()
{
    //create a map in which we will save if a wall has been instantiated
    bool[,] map = new bool[tex.width, tex.height];
    for (int z = 0; z < tex.height; z++)
        for (int x = 0; x < tex.width; x++)
            map[x,z] = false;
    for (int z = 0; z < tex.height; z++)
        for (int x = 0; x < tex.width; x++)
            if(!map[x,z]) // for each pixel not instantiated
            {
                Color color = tex.GetPixel(x, z);
                if(color.a != 0) // if there is a wall
                {
                    GameObject newWall = (GameObject)GameObject.Instantiate(cube, new Vector3(x, y, 0), Quaternion.identity);
                    bool horizontal = false;
                    if (x != tex.width-1)
                        if (tex.GetPixel(x+1, z).a != 0 && !map[x+1, z]) // if the wall is horizontal
                        {
                            int x2;
                            for (x2 = x; !map[x2, z] && tex.GetPixel(x2, z).a != 0; x2++) // find the end and save the pixels affected.
                                map[x2, z] = true;
                            newWall.transform.Translate(Vector3.right * (x2 - x) / 2);
                            newWall.transform.localScale.Set(x2-x,1,1);
                            // Modify the wall so that he fits to all pixels affected
                            horizontal = true;
                        }
                    if(!horizontal)
                        if (z != tex.height - 1)
                            if (tex.GetPixel(x, z+1).a != 0 && !map[x, z+1])
                            {
                                int z2;
                                for (z2 = z; !map[x, z2] && tex.GetPixel(x, z2).a != 0; z2++) // find the end and save the pixels affected.
                                    map[x, z2] = true;
                                newWall.transform.Translate(Vector3.forward * (z2 - z) / 2);
                                newWall.transform.localScale.Set(1, 1, z2-z);
                                // Modify the wall so that he fits to all pixels affected
                            }
                }
            }
}

I would recommend googling code on generating regions. Probably the best approach would be to create a region based on color (think magic wand tool), then using that region to generate a mesh. You could paint with different colors to have different items like dirt, grass, trees, water, and prefabs like houses.

Incidentally, you used the word terrain, so I would be remiss if I didn’t point out that you can generate terrains using heightmaps, but based upon the drawing I assume you want walls or buildings.