Hello Guest

Author Topic: Best practice for programming loop to create tile map layers?  (Read 8529 times)

Euthyphro

  • Newbie
  • *
  • Posts: 20
    • View Profile
I have about 40 tile maps and multiple layers, rather than modifying each one by hand and wishing I was a robot, I'm trying to write a script to do that. The problem is that this is leaving the old layers under the render data game object and creating the layers rather oddly. Obviously I'm doing this wrong, what is the best practice to add/remove tile map layers through code to ensure everything is taken care of?

Here is my code for what I have:

Code: [Select]
if(GUILayout.Button("Create Tile Map Layers"))
{
List<tk2dTileMapData> tileMapDataList = new List<tk2dTileMapData>();
tileMaps = FindObjectsOfType(typeof(tk2dTileMap)) as tk2dTileMap[];
Debug.LogError("Size: "+tileMaps.Count().ToString());
foreach (tk2dTileMap tileMap in tileMaps)
{
tileMap.data.tileMapLayers.Clear();
tileMap.BeginEditMode();

for(int i = 0; i < 5; i++)
{
tk2dRuntime.TileMap.LayerInfo newLayer = new tk2dRuntime.TileMap.LayerInfo();
newLayer.name = "Layer "+i.ToString();
newLayer.generateCollider = false;
newLayer.useColor = true;
newLayer.z = i;
newLayer.unityLayer = 20 + i;
newLayer.sortingOrder = i;
newLayer.hash = 0x70d32b98;
if(i == 1)
{
newLayer.generateCollider = true;

}
if(i == 0)
{
tileMap.data.tileMapLayers[i] = newLayer;
}
else tileMap.data.tileMapLayers.Add(newLayer);

Debug.LogError(tileMap.name+" i:"+i.ToString());
}
tileMap.EndEditMode();
}
}



unikronsoftware

  • Administrator
  • Hero Member
  • *****
  • Posts: 9709
    • View Profile
Re: Best practice for programming loop to create tile map layers?
« Reply #1 on: July 12, 2014, 09:48:33 pm »
If you wnat to delete a layer, look at tk2dTIleMapUtility.DeleteLayer. That deletes a layer correct - its what the editor code uses.

Euthyphro

  • Newbie
  • *
  • Posts: 20
    • View Profile
Re: Best practice for programming loop to create tile map layers?
« Reply #2 on: July 13, 2014, 10:45:58 pm »
If you wnat to delete a layer, look at tk2dTIleMapUtility.DeleteLayer. That deletes a layer correct - its what the editor code uses.

Any chance on a quick little tutorial on looping through to create tile map layers properly? This is getting extremely messy having to modify methods and functions that are not public and either rewrite them or change the tk2d scripts.

The problem I'm having creating them is that they aren't all instantiating after having essentially copied and pasted the FindOrCreateLayer(tilemap, name) function. I guess there is more to it but that is my point, it's getting very messy because you can't just access tk2deditor from outside scripts without doing several other things.

unikronsoftware

  • Administrator
  • Hero Member
  • *****
  • Posts: 9709
    • View Profile
Re: Best practice for programming loop to create tile map layers?
« Reply #3 on: July 14, 2014, 12:49:15 pm »
Code: [Select]
int layerId = -1;
for (int i = 0; i < tm.data.Layers.Length; ++i) {
if (tm.data.Layers[i].name == "Blocker") {
layerId = i;
break;
}
}

tm.BeginEditMode();
if (layerId != -1) {
tk2dEditor.TileMap.TileMapUtility.DeleteLayer(tm, layerId);
}

int newLayerIndex = tk2dEditor.TileMap.TileMapUtility.FindOrCreateLayer(tm, "Hello");
tm.EndEditMode();

You dont need to modify or copy any of the functions. tk2dEditor IS accessible from editor scripts, and if you're doing that in the editor you should be using an editor script.

Euthyphro

  • Newbie
  • *
  • Posts: 20
    • View Profile
Re: Best practice for programming loop to create tile map layers?
« Reply #4 on: July 18, 2014, 01:17:02 am »


You dont need to modify or copy any of the functions. tk2dEditor IS accessible from editor scripts, and if you're doing that in the editor you should be using an editor script.

How might I do that?  The beginning of my class looks like this, and as far as I'm aware, this would make it an editor script. With that said, not able to access tk2dEditor. "Using tk2dEditor" is no go and calling tk2dEditor from anywhere it doesn't show up within any methods or functions of this editor script.


*Edit* I think I got it, I put it in the same folder as tk2deditor and it seems to be working now.

Code: [Select]
#if UNITY_EDITOR
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using tk2dRuntime.TileMap;

[CustomEditor(typeof(TileDataScript))] //tile data script attached to GameManager GameObject.
public class TileDataEditor : Editor {

/***
functions and methods etc

*/

}
#endif
« Last Edit: July 18, 2014, 01:55:15 am by Euthyphro »

unikronsoftware

  • Administrator
  • Hero Member
  • *****
  • Posts: 9709
    • View Profile
Re: Best practice for programming loop to create tile map layers?
« Reply #5 on: July 18, 2014, 02:43:34 pm »
And editor script can be in any folder called "Editor". It doesn't have to be in the same dir. But otherwise, glad you've got that working.

Euthyphro

  • Newbie
  • *
  • Posts: 20
    • View Profile
Re: Best practice for programming loop to create tile map layers?
« Reply #6 on: August 04, 2014, 07:41:43 pm »
Since having done this edit I seem to be having a problem with the TileMapData file. It works perfectly until I close the editor and open. When I reopen the editor, the tilemap render layers create a new gameobject for the layers.

Here is a screen grab of before and after followed by code based on your suggestions - which like I said, works wonderfully until closing/opening - in which case I then have to rebuild the layers. Likewise I cannot compile an exe without this same issue happening when opening the exe after.
Before close:

After close/reopen of Unity (this also happens when compiling the game into exe and running out of the editor)


Code: [Select]
public tk2dTileMap[] tileMaps;

public void BuildLayers()
{
                       tileMaps = FindObjectsOfType(typeof(tk2dTileMap)) as tk2dTileMap[];
Debug.Log("Tile map count: "+tileMaps.Count().ToString());
int counterMaps = 0;
int counterLayers = 0;
foreach (tk2dTileMap tileMap in tileMaps)
{
                                //not entirely sure why this is here, it was in example given by unikronsoftware
int layerId = -1;
for (int i = 0; i < tileMap.data.Layers.Length; ++i) {
if (tileMap.data.Layers[i].name == "Blocker") {
layerId = i;
break;
}
}

tileMap.BeginEditMode();
                                //clear old layers out since we'll be recreating them. May not be necessary as we can just use "FindOrCrateLayer()" but kept in for now.
for(int i = 0; i <tileMap.data.Layers.Length; i++)
{
Debug.LogError("Deleting layer: "+tileMap.data.Layers[i].name);
tk2dEditor.TileMap.TileMapUtility.DeleteLayer(tileMap,  i);


}

        //set tilemap so that we are using the sorting layer sort method
tileMap.data.useSortingLayers = true;
for(int i = 0; i < 6; i++)
{
int newLayerIndex = tk2dEditor.TileMap.TileMapUtility.FindOrCreateLayer(tileMap, "Layer "+i.ToString());
// tileMap.data.Layers[].generateCollider = true;

                                       
                                        //index from TileMapUtility is oddly not ordered based on the order it was created. Sometimes
                                        // the new layer index returned is different. i.e. this is created from 0 to 5 but sometimes index returned is not sequential to the order created.
                                        //instead we just give the layer the name "Layer +" index number.
tileMap.data.Layers[newLayerIndex].name = "Layer "+newLayerIndex.ToString(); 
tileMap.data.Layers[newLayerIndex].z = 1;
tileMap.data.Layers[newLayerIndex].unityLayer = 20+i;
int t = 5-i;
tileMap.data.Layers[newLayerIndex].sortingLayerName = "TileMapLayer"+t.ToString();
if(newLayerIndex != 0)
{
tileMap.data.Layers[newLayerIndex].generateCollider = false;
}
counterLayers++;
tileMap.Layers[newLayerIndex].Optimize();
}
counterMaps++;
Debug.Log("Completed maps: "+counterMaps.ToString()+" Completed layers: "+counterLayers.ToString());
tileMap.EndEditMode();

}
}
« Last Edit: August 04, 2014, 08:13:56 pm by Euthyphro »

unikronsoftware

  • Administrator
  • Hero Member
  • *****
  • Posts: 9709
    • View Profile
Re: Best practice for programming loop to create tile map layers?
« Reply #7 on: August 05, 2014, 10:35:55 pm »
Where are you running that code from? It looks like its losing the references to the objects - you might need to call SetDirty on the tilemap / tilemap data objects....

Euthyphro

  • Newbie
  • *
  • Posts: 20
    • View Profile
Re: Best practice for programming loop to create tile map layers?
« Reply #8 on: August 07, 2014, 06:43:25 am »
That fixed it, thanks again!