How can I reference rule tiles across different tilemaps?

Right now I’m making a top down game. I’m using a custom rule tile for the walls because I need to check if the neighboring tile is a ground tile since that would affect where the light is coming from. For example if a wall tile only has a ground tile below it but not above it it should place this tile:206633-wall-down.png
But if the wall tile has ground tiles above it and below it it would be:206634-wall-up-and-down.png
Here is the code I’m using:

     using System.Collections;
     using System.Collections.Generic;
     using UnityEngine;
     using UnityEngine.Tilemaps;
     
     [CreateAssetMenu]
     public class WallRuleTileScript : RuleTile<WallRuleTileScript.Neighbor> {
         public TileBase ground;
     
         public class Neighbor : RuleTile.TilingRule.Neighbor {
             public const int Ground = 3;
             public const int NotGround = 4;
         }
     
         public override bool RuleMatch(int neighbor, TileBase tile) {
             switch (neighbor) {
                 case Neighbor.This: return tile == this;
                 case Neighbor.NotThis: return tile != this;
                 case Neighbor.Ground: return tile == ground;
                 case Neighbor.NotGround: return tile != ground;
             }
             return base.RuleMatch(neighbor, tile);
         }
     }

So right now my problem is that for this to work I need both the ground and the walls to be in the same tilemap, however, I need to have them in separate tilemaps so I can have them in separate layers. How could I make the wall tiles check the other tilemap for the ground tiles?

Depending on your exact approach, there could be a lot of ways to handle this. As one approach, let’s look at how assigning tileID values might work:

const int tileSetID = 1000000; // X --- ---
const int tileTypeID = 1000; // - XXX ---
const int tileSubtypeID = 1; // - --- XXX

With a baseline in place, let’s look at how variations on each might be assigned:

Tile Sets:

Field: 1

City: 2

Dungeon: 3

Tile Types:

Ground: 1

Wall: 2

Barrel: 3

Tile Subtypes:

Clean: 1

Dirty: 2

Battered: 3

With that concept in mind, there’s something that can be immediately noticed; if any tile is assigned a value of [0] in any of those fields, it can be treated as invalid. That way, accidents/non-assignments will be readily apparent.

Now, as for using them… After values are assigned, you compare them by either sending the relevant value(s) or comparing combined IDs directly:

public static int GetTileSet(int tileID)
{
	return tileID / tileSetID;
}
public static int GetTileType(int tileID)
{
	return (tileID % tileSetID) / tileTypeID;
}
public static int GetTileSubtypeID(int tileID)
{
	return tileID % tileSubtypeID;
}

Similarly, by having those values assigned to “Tile” objects directly, you can just compare one with another:

public override bool RuleMatch(int neighbor, TileBase tile)
{
	switch(neighbor)
	{
		case Neighbor.This: return tile.tileType == this.tileType;
		case Neighbor.NotThis: return tile.tileType != this.tileType;
		case Neighbor.Ground: return tile.tileType != TileTypes.Ground; // e.g. 1
		case Neighbor.NotGround: return tile.tileType != TileTypes.Ground; // e.g. 1
	}
}

Overall, there are a lot of options in how you can handle this, but the main thing you'll want to do (probably) is figure out values to assign for your own use and reuse. While you *can* aim for a more "object-oriented" approach (essentially, complex derived classes and checks for them), this is probably a situation where you would want to keep things as simple, clean, and straightforward as you reasonably can, for the sake of performance and potential data saving/loading (hence the 7+ -digit example combined TileIDs).