To define how Unity creates Tiles from a texture, create a Tile Template Asset, which is a ScriptableObject
you can inherit from and implement in a C# script.
This would allow you to change the default behaviour for creating and placing Tiles in the Tile Palette. For example, you could create a single Rule Tile from the Sprites in the texture, instead of creating a Tile for every SpriteA 2D graphic objects. If you are used to working in 3D, Sprites are essentially just standard textures but there are special techniques for combining and managing sprite textures for efficiency and convenience during development. More info
See in Glossary, simplifying your TilemapA GameObject that allows you to quickly create 2D levels using tiles and a grid overlay. More info
See in Glossary painting experience.
Implement the following function in your C# Tile Template script:
public abstract void CreateTileAssets(Texture2D texture2D
, IEnumerable<Sprite> sprites
, ref List<TileChangeData> tilesToAdd);
You will be given a reference to the paired Texture and all the Sprites the paired Texture has. Your output should be a list of Tiles that you want generated and their position offsets for placement into the Tile Palette generated by the Tile Set asset.
The following is an example of an implemented Tile Template Asset, the PositionTileTemplate. The PositionTileTemplate places Tiles in the Tile Set based on a corresponding list of positions passed in by the user, instead of being automatically determined by Unity. This allows users to place all Tiles horizontally if they wish to.
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
namespace UnityEditor.Tilemaps
{
/// <summary>
/// Tile Template which places created Tiles into fixed positions passed with this Template
/// </summary>
[Serializable]
public class PositionTileTemplate : TileTemplate
{
[SerializeField]
private List<Vector3Int> m_Positions;
/// <summary>
/// Positions to place Sprites into Tile Palette
/// </summary>
public IEnumerable<Vector3Int> positions
{
get => m_Positions;
set
{
if (m_Positions == null)
m_Positions = new List<Vector3Int>();
m_Positions.Clear();
m_Positions.AddRange(value);
}
}
/// <summary>
/// Tile Template which places created Tiles into fixed positions passed with this Template
/// </summary>
/// <param name="positions">Positions to place Sprites into Tile Palette</param>
public PositionTileTemplate(IEnumerable<Vector3Int> positions)
{
m_Positions = new List<Vector3Int>();
m_Positions.AddRange(positions);
}
private static IEnumerable<(T1, T2)> MultipleEnumerate<T1, T2>(IEnumerable<T1> t1s, IEnumerable<T2> t2s)
{
using IEnumerator<T1> enum1 = t1s.GetEnumerator();
using IEnumerator<T2> enum2 = t2s.GetEnumerator();
while (enum1.MoveNext() && enum2.MoveNext())
yield return (enum1.Current, enum2.Current);
}
/// <summary>
/// Creates a List of TileBase Assets from Texture2D and Sprites with placement
/// data onto a Tile Palette.
/// </summary>
/// <param name="texture2D">Texture2D to generate Tile Assets from.</param>
/// <param name="sprites">Sprites to generate Tile Assets from. Each Sprite will be created as a Tile asset and mapped to a position in order.</param>
/// <param name="tilesToAdd">Tile Assets and placement data to generate.</param>
public override void CreateTileAssets(Texture2D texture2D, IEnumerable<Sprite> sprites, ref List<TileChangeData> tilesToAdd)
{
var i = 0;
var tileMap = new Dictionary<Sprite, TileBase>();
foreach (var (textureSprite, position) in MultipleEnumerate(sprites, positions))
{
if (!tileMap.TryGetValue(textureSprite, out TileBase tile))
{
tile = ScriptableObject.CreateInstance<Tile>();
tile.name = $"Tile {i}";
tile.sprite = textureSprite;
tileMap.Add(textureSprite, tile);
}
if (tile == null)
continue;
tilesToAdd.Add(new TileChangeData()
{
position = position,
tile = tile,
transform = Matrix4x4.identity,
color = Color.white
});
}
}
}
}