How to update / refresh the sprite in a tilemap at runtime? Trying to understand how "RefreshTile" works

I am trying to fix this weird issue with Unity Tilemaps and prefabs, where, if you set both a sprite and game object, then it places both of those in the tilemap, and at runtime, if you move the game object, there’s a sprite left behind. Unfortunately, not setting the sprite means that you can’t see the game object in the tile palette, which is no good.

I had this idea to try and show the sprite in the editor, and hide it at runtime, but modifying it’s colour:

tileData.color = new Color(0,0,0,0);

That will hide the sprite, but it hides it in the tilemap and the tilepalette. So, I really only want that code to run at runtime, but not in the editor. I tried doing this:

public override void GetTileData(Vector3Int position, ITilemap tilemap, ref TileData tileData)
{
    base.GetTileData(position, tilemap, ref tileData);
 
    tileData.gameObject = tilePrefab;
 
    // Set the tile's sprite for the Tile Palette to the preview sprite
    tileData.sprite = previewSprite;
    //tileData.color = new Color(0f, 0f, 0f, 0f);
 
    // Check if the game is running (not in the editor)
    if (!Application.isPlaying)
    {
        tileData.color = new Color(1,1,1,1); // show the sprite in the editor
    }
    else
    {
        tileData.color = new Color(0,0,0,0); // hide the sprite during gameplay
    }
}
public override void RefreshTile(Vector3Int position, ITilemap tilemap)
{
    tilemap.RefreshTile(position);
}

But, it doesn’t seem to work. Does anyone see a better way to handle this? I don’t fully understand how this Unity class works, or the RefreshTile method. Application.Playing seems like a good idea, but it appears not to function as I would expect in this class. Thanks.

GetTileData and RefreshTile might only be called when the tile or neighboring tiles are being edited. You could make an editor script that refreshes the tiles on all of the tilemap at once to update the sprite color.

You might be able to achieve something with a script like this put inside an Editor-only folder, though it would need a few edits to best suit your needs:

using UnityEngine;
using UnityEngine.Tilemaps;
using UnityEditor;

public static class TilemapRefresher
{
    [InitializeOnLoadMethod]
    private static void Initialize()
    {
        EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
    }
 
    private static void OnPlayModeStateChanged(PlayModeStateChange change)
    {
         foreach (Tilemap t in FindObjectsOfType<Tilemap>())
         {
             t.RefreshAllTiles();
         }
    }
}

Something else to consider is to detach your GameObjects from the tilemap if they’re going to be moving around, but of course that depends on your needs. I wouldn’t recommend it though, as tiles with GameObjects attached would preferably share positions.