Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

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!