Programmatically generate a Tilemap Palette
Published 8 months ago
How to programmatically generate a Tilemap Palette

What is a Tilemap Palette

The Tilemap Palette is an asset used by the “Tile Palette” window to organize the tiles together so you can paint you tiles onto the Tilemap of the scene.

Why generating a Tile Palette programmatically?

There is no common reasons for doing this. It is why in the time I wrote this article, there was nothing about it. Let’s just say that when you’re generating bunch of tiles programmatically, you may also want to generate multiple Tilemap Palette to group them automatically.
This is usually easy to drag sprites to the “Tilemap Palette” window to generate tiles. But you may have tons of sprites that needs to be place in separate “Tilemap Palette”. If you doesn’t want to drag them manually you will probably write a custom script editor that will analyze the name of the sprite and put it in the right “Tile Palette”.

The structure

The Tilemap Palette structure is similar to when you add a Tilemap in the hierarchy view.

There is no component that represents the Tilemap Palette specifically. This is simply a Grid with a Tilemap. The only difference here is an object called “Palette Settings”. To find the object type I had to write a script editor to expose its type. This object is a GridPalette and here is the definition from the documentation: GridPalette stores settings for Palette assets when shown in the Palette window.
So, in order to programmatically generate a Tilemap Palette, we have to recreate this structure.

Here is the code

using System.Collections; using System.Collections.Generic; using UnityEditor; using UnityEngine; using UnityEngine.Tilemaps; /// <summary> /// Utility class for the Tilemap Palette. /// </summary> public static class TilemapPaletteUtils { /// <summary> /// Get (or create if the asset doesn't exist) a Tilemap Palette. /// </summary> /// <param name="a_assetPath">The asset path</param> /// <returns>Return the Tilemap</returns> public static Tilemap GetOrCreateTilemapPalette(string a_assetPath) { Grid grid = AssetDatabase.LoadAssetAtPath<Grid>(a_assetPath); Tilemap tilemap = null; if (grid != null) { tilemap = grid.gameObject.GetComponentInChildren<Tilemap>(); } if (tilemap == null) { tilemap = CreateTilemapPalette(a_assetPath); } else { // Check the asset if under version control. if (UnityEditor.VersionControl.Provider.enabled) { UnityEditor.VersionControl.Provider.Checkout(tilemap, UnityEditor.VersionControl.CheckoutMode.Both); } } return tilemap; } /// <summary> /// Create the Tilemap Palette prefab asset. /// </summary> /// <param name="a_assetPath"></param> /// <returns>Return a Tilemap</returns> public static Tilemap CreateTilemapPalette(string a_assetPath) { // Create the GameObject for the Grid. GameObject go = new GameObject(); = System.IO.Path.GetFileNameWithoutExtension(a_assetPath); Grid grid = go.AddComponent<Grid>(); // Create the GameObject for the Tilemap. GameObject layer1GO = new GameObject(); = "Layer1"; layer1GO.transform.SetParent(go.transform); Tilemap tilemap = layer1GO.AddComponent<Tilemap>(); TilemapRenderer tilemapRenderer = layer1GO.AddComponent<TilemapRenderer>(); tilemapRenderer.enabled = false; // Create the GameObject for the GridPalette. GridPalette palette = ScriptableObject.CreateInstance<GridPalette>(); = "Palette Settings"; // Generate and save the prefab. Object prefab = PrefabUtility.CreateEmptyPrefab(a_assetPath); PrefabUtility.ReplacePrefab(go, prefab); AssetDatabase.AddObjectToAsset(palette, prefab); AssetDatabase.SaveAssets(); return tilemap; } }
As you may notice, I chose to return a Tilemap instead of the prefab to avoid having to retrieve the Tilemap each time. This is what you want to access after generating the Tilemap Palette to place your tiles. And probably the only thing you want to access from the prefab. Otherwise, you can always create a wrapper class that could give you an easy access to all three objects of the prefab.
using System.Collections; using System.Collections.Generic; using UnityEditor; using UnityEngine; using UnityEngine.Tilemaps; /// <summary> /// This class wrap a Tilemap Palette prefab. /// </summary> public class TilemapPalette { #region ATTRIBUTES private Grid m_grid; private Tilemap m_tilemap; private GridPalette m_gridPalette; #endregion // ATTRIBUTES #region PROPERTIES public Grid Grid { get { return m_grid; } } public Tilemap Tilemap { get { return m_tilemap; } } public GridPalette GridPalette { get { return m_gridPalette; } } #endregion // PROPERTIES #region CONSTRUCTORS public TilemapPalette(Grid a_grid) { m_grid = a_grid; m_tilemap = m_grid.gameObject.GetComponentInChildren<Tilemap>(true); string assetPath = AssetDatabase.GetAssetPath(a_grid); m_gridPalette = AssetDatabase.LoadAssetAtPath<GridPalette>(assetPath); } public TilemapPalette(Grid a_grid, Tilemap a_tilemap, GridPalette a_gridPalette) { m_grid = a_grid; m_tilemap = a_tilemap; m_gridPalette = a_gridPalette; } #endregion // CONSTRUCTORS }
Alexandre Martel
Creative Developer - Programmer