Search Unity

Tilemap Bounds Issue

Discussion in '2D' started by TomTheMan59, Mar 18, 2021.

  1. TomTheMan59

    TomTheMan59

    Joined:
    Mar 8, 2021
    Posts:
    356
    I am trying to see if a collider is within a tilemap. I cannot use compositeCollider OverlapCollider method as I have to use outline mode.

    I need to determine if my collider is within the bounds of the tiles on the tilemap. Using TilemapRenderer.Intersect doesn't work because its just using the rectangle bounds, not the bounds of the tiles.

    Is there a optimized way to do this?

    image.png

    Essentially, I need to determine if the collider is over any of these tiles.

    Cheers!
     
  2. ChuanXin

    ChuanXin

    Unity Technologies

    Joined:
    Apr 7, 2015
    Posts:
    1,068
    Hi, could you share the reason why you would prefer to use the outline mode instead of polygon? Thanks!
     
  3. TomTheMan59

    TomTheMan59

    Joined:
    Mar 8, 2021
    Posts:
    356
    I am using outline because if I use polygon my character will sometimes hit a ghost vertex.

    Is my only solution to have all the tiles have collision so the entire map is a collider instead of only the outer tiles? (I keep the center tiles without collision for performance since there is no need). This means that I would have to duplicate the terrain tilemap and set to isTrigger just for detecting. Also I would have to do this at runtime because keeping track if I changed a tilemap and reduplicating it is a pain.

    Is there no way to detect if the player is intersecting with the tilemap in a optimized way?

    EDIT: I ended up just changing from outline mode to polygon mode when my player dies so I can check if my objects are over the tilemap and when the player respawns, switching back. Is this bad for performance?

    Cheers!
     
    Last edited: Mar 19, 2021
  4. ChuanXin

    ChuanXin

    Unity Technologies

    Joined:
    Apr 7, 2015
    Posts:
    1,068
    Would it be possible to share your project through the Unity Bug Reporter and post the case number here so that we could check this out?

    This would likely be bad for performance as the size of your Tilemap increases.

    Assuming that an approximation of intersection works (depending on the shapes of your colliders for your objects and your tiles), you could instead get the bounds of your objects and check if the bounds coincide with the Tiles on the Tilemap? The following would be pseudo-code to do so:

    Code (CSharp):
    1. var bounds = myObject.GetComponent<Collider2D>.bounds;
    2. var boundsInt = new BoundsInt(Vector3Int.FloorToInt(bounds.position), Vector3Int.CeilToInt(bounds.size));
    3. foreach (var position in boundsInt.allPositionsWithin)
    4. {
    5.     if (tilemap.HasTile(position))
    6.          return true;
    7. }
    8. return false;
     
    TomTheMan59 likes this.
  5. TomTheMan59

    TomTheMan59

    Joined:
    Mar 8, 2021
    Posts:
    356
    It has been a very long time (over half a year) that I was having this issue. I will try to reproduce it again in my project.

    EDIT: I saw this by @MelvMay "If you're using polygon mode then you're still producing multiple physics shapes which are not a continuous surface and are no different than multiple colliders." about using polygon mode that it will still causes ghost collision.

    I couldn't do approximates like this. If the object is outside the tilemap and this could still detects its inside, I would't know and I would turn off the objects collision. That would be very bad. :(

    I profiled switching from outline to polygon and on my largest map and it is 9.8ms. This doesn't seem bad? But I am a noob.

    Thanks for looking into this.

    Cheers!
     
    Last edited: Mar 25, 2021
  6. ChuanXin

    ChuanXin

    Unity Technologies

    Joined:
    Apr 7, 2015
    Posts:
    1,068
    That isn't very good. For reference, a game at 60 fps would take 16.6ms per frame.

    An alternative would be to copy the collider shape from your CompositeCollider2D to a separate PolygonCollider2D, and setting the layer for the separate PolygonColllider2D GameObject, so that it does not interfere with your normal collisions. This would reduce the time spent in switching between outline/polygon modes.

    Code (CSharp):
    1. void Start()
    2.     {
    3.         var composite = GetComponent<CompositeCollider2D>();
    4.         var polygon = GetComponent<PolygonCollider2D>();
    5.  
    6.         polygon.pathCount = composite.pathCount;
    7.         for (int i = 0; i < composite.pathCount; ++i)
    8.         {
    9.             var compositePath = new List<Vector2>(composite.GetPathPointCount(0));
    10.             composite.GetPath(i, compositePath);
    11.             polygon.SetPath(i, compositePath);
    12.         }
    13.     }
    I am probably not fully understanding your use-case for this collision detection. Would it be possible to provide more details and show some screenshots of the overlaps you want to detect? Thanks!

    That would be great!
     
    TomTheMan59 likes this.
  7. TomTheMan59

    TomTheMan59

    Joined:
    Mar 8, 2021
    Posts:
    356
    I was originally doing that. I just thought that having two versions of a large polygon in the game was worst for performance than doing it the quicker way. Maybe even just instantiating the tilemap on start and deleting everything except the composite collider would also work?

    Here are two images explaining the issue! In these images, the red rectangles are both apart of the terrain tilemap. They cannot really be separated into ceiling and floor in my game or I would just have ceiling/floor tilemap and it would all work.

    Screenshot 2021-03-26 at 10.43.46 AM.png Screenshot 2021-03-26 at 10.45.55 AM.png

    In the second image, if the collider is even slightly to the left of the terrain, using the approximate will cause it to detect the overlap and it will still fall through the floor.

    This is a different issue though then my original post. Thanks for your time! I think I will just pick a point inside the collider and if the collider overlaps the terrain but that point doesn't, don't turn off the collision.

    Thanks again for looking into this!
     
    Last edited: Mar 26, 2021
  8. ChuanXin

    ChuanXin

    Unity Technologies

    Joined:
    Apr 7, 2015
    Posts:
    1,068
    That should work as well as long as the composite collider is not updated, eg. colliders were added or removed.

    Based on my understanding of your use-case, perhaps the Platform Effector (https://docs.unity3d.com/Manual/class-PlatformEffector2D.html) would be useful to you? This allows collision based on the angle of collision which could be what you are looking for?
     
  9. TomTheMan59

    TomTheMan59

    Joined:
    Mar 8, 2021
    Posts:
    356
    Thanks for all the help! I really appreciate it.

    Cheers!