Tile based map via instantiate?

Heya,

I tried to generate a rather small map with just 101*101 tiles and it took unity over 30 seconds to do just that.
My project is completely empty apart from the standard assets. So I am wondering if instanciating is the right way to do this kind of stuff at all. In this case I just instantiated a prefab containing a plane with a small texture and I used this simple code to generate it:

		for(int x=-radius;x<=radius;x++)
		{
			for(int z=-radius;z<=radius;z++)
			{
				GameObject temp=Instantiate(maptile,new Vector3(x*_width,0,z*_length)  ,Quaternion.identity)as GameObject;
				temp.transform.parent=startingpoint.transform;
				temp.name=count.ToString();
				count++;
			}
		}

So with this already taking 30 seconds I am wondering if there is a better/faster way to generate a tile based map, where every tile can have different properties (somewhat like minecraft).

It’s not a good idea to have so many individual objects; that’s over 10,000. (Which is even worse than being over 9000. :wink: ) You should use the Mesh class to construct the map, that way it will be just one object, or a few objects if you do it in chunks.

–Eric

But as far as I understand it, it would not be possible with a mesh to dynamically alter it. Lets say that instead of a grid of 100x100 tiles there would be one mesh. Lets say that several of these tiles represent a wall and a player destroys this wall and therefore would alter the tile in terms of look, movement, line of sight and so on.
Maybe you are familiar with Jagged Alliance 1/2 or the first X-Com games. Is there a way to make maps like these work in unity?
Or is it a limitation in this system and one of the reasons why in a lot of modern games you can’t destroy just any wall, but only use your dynamite in 3 pre-determined spots?
A different example would be a game live Civ4, which also has more than 10 000 tiles in it’s maps, All with their individual textures which can change during gameplay. What would be the right direction in creating such maps?

Yes it will, that’s what all the 2D sprite/tile systems do, not to mention the various Minecraft systems. You just rebuild the mesh as necessary.

–Eric

check that :
http://forum.unity3d.com/threads/7613-Simple-2D-game-example

I checked this 2D example before, but I don’t think that it can really help me.
As far as I see it in this project basically the is done as in my code above - except of two special things:

  1. the tiles itself consists of graphics used for collision detection
  2. there aren’t objects for all tiles. Just for the walls basically.

So with this system you could reduce a “room” of 10x10 tiles to maybe 60 planes instead of 100 and of course in empty regions you can save even more.
But with this it would get more complicated if you wanted to do different backgrounds. I guess you can combine some background tiles to one plane in that way, but you would need to change the background plane from “outside” to “inside”. It would be harder to do a path, change water to sand, to mud, to grass, to rock. Having a carpet would need to be a seperate object. In addition you would need to have another set of objects in the background to store all the rest of the data for the tiles not being displayed. Like if there are objects on it, if you can walk there and so on.
So for this space shooter game it seems to be a good solution, but I am not sure what it would be in maps like Jagged Alliance, XCom or Civilization.

I will take a deeper look about this combine mesh thingy Eric mentioned, but at the moment It is quite unclear to me how this should work (in code and in terms of mechanics).

Do you need all of the 101x101 tiles to be seen? If not you could just disable all objects that are not within viewable radius. Beyond that you could make a pool system that will reuse objects.

Yes, that was something I wanted to do anyways as my 101x101 example was just a “start small” thing (actually in my first attempt I tried 201201 and unity crashed). But you may be right to keep it even smaller. I guess in the end 3030 to 50*50 visible at once would do the job size wise. What I had in mind was to procedurally generate the map and make it unlmited, with loading and unloading stuff. But I guess this would be more effective if you already have a “big size” available at all times.
But as I am still a newb in Unity, I take step after step.
I was just shocked that unity already had that much of a problem with 101x101 planes and I guessed that there are better options.

On the first look it works quite well to generate the mesh from scratch. Just tested it with 10000 tiles and only one material.
The time needed for that is about zero. While I would need to do several more conditionals and so on for more complex stuff and several materials I guess it would be fine even if it took 10 times longer then. The only obstacle here is that a mesh can’t have more than 65k vertices, but that equals more than 100x100 tiles per mesh and should work fine.
So thanks to all for your help!

For those finding this thread and looking for more information - I got the info about these mechanics by the following links:

and

and the function I built for a simple test (straight line of 10000 tiles):

    void Start()
    {
        GetComponent<MeshFilter>().mesh = CreateTonsPlaneMesh();
    }
	
	Mesh CreateTonsPlaneMesh()
    {
		int counter=10000;
        Mesh mesh = new Mesh();
		Vector3[] vertices = new Vector3[counter*4];
		for (int i = 0; i < counter; i++) 
		{
			vertices[i*4]	=new Vector3(1+i*2	,0, 1);
			vertices[i*4+1]	=new Vector3(1+i*2	,0,-1);
			vertices[i*4+2]	=new Vector3(-1+i*2	,0, 1);
			vertices[i*4+3]	=new Vector3(-1+i*2	,0,-1);
		}
		
		/*
        Vector3[] vertices = new Vector3[]
        {
            new Vector3( 1, 0,  1),
            new Vector3( 1, 0, -1),
            new Vector3(-1, 0,  1),
            new Vector3(-1, 0, -1),
			
			
			new Vector3( 3, 0,  1), /2nd run
			new Vector3( 3, 0, -1), /2nd run
			new Vector3( 1, 0,  1), /2nd run
			new Vector3( 1, 0, -1), /2nd run
			
        };
		 */
		
		Vector2[] uv = new Vector2[counter*4];
		
		for (int i = 0; i < counter; i++) 
		{
			uv[i*4]		=new Vector2(1,1);
			uv[i*4+1]	=new Vector2(1,0);
			uv[i*4+2]	=new Vector2(0,1);
			uv[i*4+3]	=new Vector2(0,0);
		}
		
		/*
        Vector2[] uv = new Vector2[]
        {
            new Vector2(1, 1),
            new Vector2(1, 0),
            new Vector2(0, 1),
            new Vector2(0, 0),
			new Vector2(1, 1), /2nd run
            new Vector2(1, 0), /2nd run
            new Vector2(0, 1), /2nd run
            new Vector2(0, 0), /2nd run
			
			
        };*/
		int[] triangles= new int[counter*6];
		
		for (int i = 0; i < counter; i++) 
		{
			triangles[i*6]		=0+i*4;
			triangles[i*6+1]	=1+i*4;
			triangles[i*6+2]	=2+i*4;
			triangles[i*6+3]	=2+i*4;
			triangles[i*6+4]	=1+i*4;
			triangles[i*6+5]	=3+i*4;
		}
		
		/*
        int[] triangles = new int[]
        {
            0, 1, 2,
            2, 1, 3,
			4, 5, 6, /2nd run
			6, 5, 7, /2nd run

        };*/

        mesh.vertices = vertices;
        mesh.uv = uv;
        mesh.triangles = triangles;

        return mesh;
    }