[Tilemap] Neighboring custom rule tiles not updating/refreshing when placing base tiles

Hello there!

I’ve been experimenting with Unity’s built-in Tilemap system and already set up 4 tiles, where 2 of them are rule tiles. The rules are identical to the ones for the Dungeon Tile from the 2D Tilemap Extras package.
The tiles are:
Grass (rule tile), has brown borders (side and corners) when the neighboring tiles are different
Water (rule tile), has sand colored borders (side and corners) when the neighboring tiles are different
Sand (base tile), 1 single sprite
Dirt (base tile), 1 single sprite

I wanted to make the grass and sand tiles be cosidered “friendly” as in the borders won’t change when they are neighbors. I also made the grass and water tiles be cosidered friendly, but only 1 way (water sprite changes, but the grass does not when they are neighboring) so I created my own script that’s inheriting from RuleTile.

With the grass and water tiles I don’t have issues, they refresh each other when placing them or just during the preview since they both are rule tiles.

The issue I have is when I place the sand tile (which is just the base tile), because the grass tile doesn’t refresh/update. It updates when I hover over the grass tile. Not actually a big deal on small maps, but I prefer not to hover over everytime when I’m updating my map. Did anyone had similar issues and found a solution? Thanks in advance!

Here is the code for the custom rule tile:

using UnityEngine;
using UnityEngine.Tilemaps;

[CreateAssetMenu]
public class FriendlyRuleTile : RuleTile<FriendlyRuleTile.Neighbor> {
    [SerializeField]
    private TileBase[] friendTiles;

    public bool customField;

    public class Neighbor : RuleTile.TilingRule.Neighbor {
        public const int ThisOrFriend = 3;
    }

    public override bool RuleMatch(int neighbor, TileBase tile) {
        switch (neighbor) {
            case Neighbor.This: return tile == this;
            case Neighbor.ThisOrFriend: return tile == this || HasFriendTile(tile);
            case Neighbor.NotThis: return tile != this;
        }
        return base.RuleMatch(neighbor, tile);
    }
    bool HasFriendTile(TileBase tile)
    {
        if (tile == null)
            return false;
        for (int i = 0; i < friendTiles.Length; i++)
        {
            if (friendTiles[i] == tile)
                return true;
        }
        return false;
    }
}

There is an “AdjacentRuleTile.cs” script in Happy Harvest demo which does what you are trying to do. It kind of looks like the RuleMatch method of yours is not correct

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Tilemaps;

namespace HappyHarvest
{
    /// <summary>
    /// This special tile add a third rule : adjacent tiles, so you can match rules with other tile than this one.
    /// See the cliff tile for an example.
    /// </summary>
    [CreateAssetMenu]
    public class AdjacentRuleTile : RuleTile<AdjacentRuleTile.Neighbor>
    {
        public class Neighbor : RuleTile.TilingRule.Neighbor
        {
            public const int Adjacent = 3;
        }

        public TileBase[] AdjacentTiles;

        public override bool RuleMatch(int neighbor, TileBase other)
        {

            switch (neighbor)
            {
                case Neighbor.Adjacent:
                    return AdjacentTiles.Contains(other);
            }

            return base.RuleMatch(neighbor, other);
        }
    }
}

Tried it and it still doesn’t work. Maybe the issue is that base tiles don’t trigger the RuleMatch/RefreshTile or some other method in rule tiles?

in this screenshot I have 3 scenarios:

  1. Placed grass tile, placed sand tile (friendly), hovered over the grass tile to refresh it
  2. Placed grass tile, placed sand tile, didn’t refresh during the preview nor after placing it
  3. Placed grass tile, placed water tile which is a rule tile (but not my custom rule tile) and it refreshed during preview and after placing it

The base Tile only ever refreshes itself (or its position), as it only knows about itself.

You could try changing the base Tile to a RuleTile with just a single Rule (by itself), so that it can update neighboring positions.

Yeah, that’s what I went with in the end. Thanks for clarifying.