Skip to content

Instantly share code, notes, and snippets.

@KHN190
Last active July 10, 2023 00:33
Show Gist options
  • Save KHN190/0d41c6a54a757d82f3a2814f5ff9d2a4 to your computer and use it in GitHub Desktop.
Save KHN190/0d41c6a54a757d82f3a2814f5ff9d2a4 to your computer and use it in GitHub Desktop.
Change Unity Tilemap's Tile sprite during runtime
using UnityEngine;
using UnityEngine.Tilemaps;
public class ChangeTiles : MonoBehaviour
{
private Tilemap tilemap;
void Start()
{
// @fixme
tilemap = GameObject.FindWithTag("Tilemap").GetComponent<Tilemap>();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
SwitchTiles();
}
}
void SwitchTiles()
{
BoundsInt bounds = tilemap.cellBounds;
bool updated = false;
foreach (Vector3Int pos in bounds.allPositionsWithin)
{
TileBase tile = tilemap.GetTile(pos);
if (tile && tile is SwitchableTile)
{
if (!updated)
{
Sprite sprite = ((SwitchableTile)tile).GetNextSprite();
((SwitchableTile)tile).sprite = sprite;
updated = true;
}
tilemap.RefreshTile(pos);
}
}
}
}
using System;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace UnityEngine.Tilemaps
{
[Serializable]
[CreateAssetMenu(fileName = "New Switchable Tile", menuName = "Tiles/Switchable Tile")]
public class SwitchableTile : Tile
{
public Sprite[] sprites;
public Tile.ColliderType m_TileColliderType;
private int spriteIndex = 0;
public override void GetTileData(Vector3Int position, ITilemap tilemap, ref TileData tileData)
{
tileData.transform = Matrix4x4.identity;
tileData.color = Color.white;
if (sprites != null && sprites.Length > 0)
{
tileData.sprite = sprites[spriteIndex];
tileData.colliderType = m_TileColliderType;
}
}
public override void RefreshTile(Vector3Int position, ITilemap tilemap)
{
tilemap.RefreshTile(position);
}
public Sprite GetNextSprite()
{
spriteIndex += 1;
spriteIndex = spriteIndex % sprites.Length;
return sprites[spriteIndex];
}
}
#if UNITY_EDITOR
[CustomEditor(typeof(SwitchableTile))]
public class SwitchableTileEditor : Editor
{
private SwitchableTile tile { get { return (target as SwitchableTile); } }
public override void OnInspectorGUI()
{
EditorGUI.BeginChangeCheck();
int count = EditorGUILayout.DelayedIntField("Number of Switchable Sprites", tile.sprites != null ? tile.sprites.Length : 0);
if (count < 0)
count = 0;
if (tile.sprites == null || tile.sprites.Length != count)
{
Array.Resize<Sprite>(ref tile.sprites, count);
}
if (count == 0)
return;
EditorGUILayout.LabelField("Place sprites shown based on the order of switching.");
EditorGUILayout.Space();
for (int i = 0; i < count; i++)
{
tile.sprites[i] = (Sprite)EditorGUILayout.ObjectField("Sprite " + (i + 1), tile.sprites[i], typeof(Sprite), false, null);
}
tile.m_TileColliderType = (Tile.ColliderType)EditorGUILayout.EnumPopup("Collider Type", tile.m_TileColliderType);
if (EditorGUI.EndChangeCheck())
EditorUtility.SetDirty(tile);
}
}
#endif
}
@KHN190
Copy link
Author

KHN190 commented Jul 10, 2023

@Sho2629 You need to create an asset as SwitchableTile, configure the sprites in order you desire - an asset is similar to prefab. Then apply your tile asset to Unity Tilemap.

The [SwitchableTile.cs](https://gist.github.com/KHN190/0d41c6a54a757d82f3a2814f5ff9d2a4#file-switchabletile-cs) needs to be placed in an Editor folder though. It is a Unity convention to organize your editor scripts.

You may want to search for keywords "Unity Tilemap", "Unity create asset" and "Unity editor script folder".

I don't understand "SwitchableTile always returns false" - it is an object / asset.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment