Search Unity

Question CustomRuleTile Rulematch() based on position of calling CustomRuleTile

Discussion in '2D' started by nucky9th, May 22, 2023.

  1. nucky9th

    nucky9th

    Joined:
    May 16, 2023
    Posts:
    6
    I am trying to make a CustomRuleTile that has a different check in RuleMatch depending on which direction the checking tile is in.

    Here is a simplified version:
    Code (CSharp):
    1.  
    2. public class TunnelCustomRuleTile : RuleTile<TunnelCustomRuleTile.Neighbor> {
    3. public bool connectionEast;
    4. public bool connectionWest;
    5. public bool connectionSouth;
    6. public bool connectionNorth;
    7.  
    8.     public class Neighbor : RuleTile.TilingRule.Neighbor {
    9.         public const int connected = 1;    
    }

    So, let's say there's a tile at 1,1. If it is checking a tile at 0,1 for this rule, then in the neighboring CustomRuleTile
    Code (CSharp):
    1. connected == connectedEast
    On the other hand, if the tile at 1,1 is checking a tile at 2,1, then
    Code (CSharp):
    1. connected == connectedWest
    Is there a way to get at this information (the relative direction of the calling RuleTile) from within the RuleMatch method?
     
  2. ChuanXin

    ChuanXin

    Unity Technologies

    Joined:
    Apr 7, 2015
    Posts:
    1,068
    Hi, you will need to customise your RuleTile a little bit to get what you need, since we do not expose the relative direction in the RuleMatch method.

    I have added an example where the relative offset which matches is passed into the RuleMatch method, you could modify this to get what you need for your usage:

    Code (CSharp):
    1.  
    2. using System;
    3. using UnityEngine;
    4. using UnityEngine.Tilemaps;
    5.  
    6. public class TunnelCustomRuleTile : RuleTile<TunnelCustomRuleTile.Neighbor>
    7. {
    8.     public bool connectionEast;
    9.     public bool connectionWest;
    10.     public bool connectionSouth;
    11.     public bool connectionNorth;
    12.  
    13.     public class Neighbor : RuleTile.TilingRule.Neighbor
    14.     {
    15.         public const int connected = 1;
    16.     }
    17.  
    18.     /// <summary>
    19.     /// Checks if there is a match given the neighbor matching rule and a Tile.
    20.     /// </summary>
    21.     /// <param name="neighbor">Neighbor matching rule.</param>
    22.     /// <param name="other">Tile to match.</param>
    23.     /// <param name="other">Tile to match.</param>
    24.     /// <returns>True if there is a match, False if not.</returns>
    25.     public virtual bool RuleMatch(int neighbor, TileBase other, Vector3Int positionOffset)
    26.     {
    27.         switch (neighbor)
    28.         {
    29.             // case Neighbor.connected: return other == this;
    30.         }
    31.         return true;
    32.     }
    33.  
    34.     /// <summary>
    35.     /// Does a Rule Match given a Tiling Rule and neighboring Tiles.
    36.     /// </summary>
    37.     /// <param name="rule">The Tiling Rule to match with.</param>
    38.     /// <param name="position">Position of the Tile on the Tilemap.</param>
    39.     /// <param name="tilemap">The tilemap to match with.</param>
    40.     /// <param name="transform">A transform matrix which will match the Rule.</param>
    41.     /// <returns>True if there is a match, False if not.</returns>
    42.     public override bool RuleMatches(TilingRule rule, Vector3Int position, ITilemap tilemap, ref Matrix4x4 transform)
    43.     {
    44.         if (RuleMatches(rule, position, tilemap, 0))
    45.         {
    46.             transform = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, 0f), Vector3.one);
    47.             return true;
    48.         }
    49.  
    50.         // Check rule against rotations of 0, 90, 180, 270
    51.         if (rule.m_RuleTransform == TilingRuleOutput.Transform.Rotated)
    52.         {
    53.             for (int angle = m_RotationAngle; angle < 360; angle += m_RotationAngle)
    54.             {
    55.                 if (RuleMatches(rule, position, tilemap, angle))
    56.                 {
    57.                     transform = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, -angle), Vector3.one);
    58.                     return true;
    59.                 }
    60.             }
    61.         }
    62.         // Check rule against x-axis, y-axis mirror
    63.         else if (rule.m_RuleTransform == TilingRuleOutput.Transform.MirrorXY)
    64.         {
    65.             if (RuleMatches(rule, position, tilemap, true, true))
    66.             {
    67.                 transform = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(-1f, -1f, 1f));
    68.                 return true;
    69.             }
    70.             if (RuleMatches(rule, position, tilemap, true, false))
    71.             {
    72.                 transform = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(-1f, 1f, 1f));
    73.                 return true;
    74.             }
    75.             if (RuleMatches(rule, position, tilemap, false, true))
    76.             {
    77.                 transform = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(1f, -1f, 1f));
    78.                 return true;
    79.             }
    80.         }
    81.         // Check rule against x-axis mirror
    82.         else if (rule.m_RuleTransform == TilingRuleOutput.Transform.MirrorX)
    83.         {
    84.             if (RuleMatches(rule, position, tilemap, true, false))
    85.             {
    86.                 transform = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(-1f, 1f, 1f));
    87.                 return true;
    88.             }
    89.         }
    90.         // Check rule against y-axis mirror
    91.         else if (rule.m_RuleTransform == TilingRuleOutput.Transform.MirrorY)
    92.         {
    93.             if (RuleMatches(rule, position, tilemap, false, true))
    94.             {
    95.                 transform = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(1f, -1f, 1f));
    96.                 return true;
    97.             }
    98.         }
    99.         // Check rule against x-axis mirror with rotations of 0, 90, 180, 270
    100.         else if (rule.m_RuleTransform == TilingRuleOutput.Transform.RotatedMirror)
    101.         {
    102.             for (int angle = 0; angle < 360; angle += m_RotationAngle)
    103.             {
    104.                 if (angle != 0 && RuleMatches(rule, position, tilemap, angle))
    105.                 {
    106.                     transform = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, -angle), Vector3.one);
    107.                     return true;
    108.                 }
    109.                 if (RuleMatches(rule, position, tilemap, angle, true))
    110.                 {
    111.                     transform = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, -angle), new Vector3(-1f, 1f, 1f));
    112.                     return true;
    113.                 }
    114.             }
    115.         }
    116.         return false;
    117.     }
    118.  
    119.     /// <summary>
    120.     /// Checks if there is a match given the neighbor matching rule and a Tile with a rotation angle.
    121.     /// </summary>
    122.     /// <param name="rule">Neighbor matching rule.</param>
    123.     /// <param name="position">Position of the Tile on the Tilemap.</param>
    124.     /// <param name="tilemap">Tilemap to match.</param>
    125.     /// <param name="angle">Rotation angle for matching.</param>
    126.     /// <returns>True if there is a match, False if not.</returns>
    127.     private new bool RuleMatches(TilingRule rule, Vector3Int position, ITilemap tilemap, int angle, bool mirrorX = false)
    128.     {
    129.         var minCount = Math.Min(rule.m_Neighbors.Count, rule.m_NeighborPositions.Count);
    130.         for (int i = 0; i < minCount ; i++)
    131.         {
    132.             var neighbor = rule.m_Neighbors[i];
    133.             var neighborPosition = rule.m_NeighborPositions[i];
    134.             if (mirrorX)
    135.                 neighborPosition = GetMirroredPosition(neighborPosition, true, false);
    136.             var positionOffset = GetRotatedPosition(neighborPosition, angle);
    137.             var other = tilemap.GetTile(GetOffsetPosition(position, positionOffset));
    138.             if (!RuleMatch(neighbor, other, positionOffset))
    139.             {
    140.                 return false;
    141.             }
    142.         }
    143.         return true;
    144.     }
    145.  
    146.     /// <summary>
    147.     /// Checks if there is a match given the neighbor matching rule and a Tile with mirrored axii.
    148.     /// </summary>
    149.     /// <param name="rule">Neighbor matching rule.</param>
    150.     /// <param name="position">Position of the Tile on the Tilemap.</param>
    151.     /// <param name="tilemap">Tilemap to match.</param>
    152.     /// <param name="mirrorX">Mirror X Axis for matching.</param>
    153.     /// <param name="mirrorY">Mirror Y Axis for matching.</param>
    154.     /// <returns>True if there is a match, False if not.</returns>
    155.     private new bool RuleMatches(TilingRule rule, Vector3Int position, ITilemap tilemap, bool mirrorX, bool mirrorY)
    156.     {
    157.         var minCount = Math.Min(rule.m_Neighbors.Count, rule.m_NeighborPositions.Count);
    158.         for (int i = 0; i < minCount; i++)
    159.         {
    160.             int neighbor = rule.m_Neighbors[i];
    161.             Vector3Int positionOffset = GetMirroredPosition(rule.m_NeighborPositions[i], mirrorX, mirrorY);
    162.             TileBase other = tilemap.GetTile(GetOffsetPosition(position, positionOffset));
    163.             if (!RuleMatch(neighbor, other, positionOffset))
    164.             {
    165.                 return false;
    166.             }
    167.         }
    168.         return true;
    169.     }
    170. }
    171.  
     
    nucky9th and MarekUnity like this.
  3. nucky9th

    nucky9th

    Joined:
    May 16, 2023
    Posts:
    6

    Awesome, thanks for the help with this!