Search Unity

[Help] Bounding Box Collision with Tileset (Without Rigidbodies)

Discussion in '2D' started by MossCairn, Oct 4, 2019.

  1. MossCairn

    MossCairn

    Joined:
    Mar 14, 2019
    Posts:
    10
    Alright, so I’m making a lot of progress with my collisions in unity, but I can’t get tilemap collision detection working quite yet. I have a grid with a composite collider, and attached to that is a tilemap with a tilemap collider. The player uses a bounding box. I’m trying to make it so that if the player’s bounding box intersects a tile, it will return true, and if it doesn't it will return false. However, my code currently gets the bounds of the entire tilemap collider, and after digging through the documentation I'm not sure how to only detect bounding box intersections with actual solid tiles.
    I should note that I'm only trying to get a true/false for if the player's bounding box is intersecting another bounding box, and possibly what objects I'm overlapping. I would also really like to avoid using Rigidbodies, because I can handle my own collisions and movement and even having kinematic rigidbodies on everything is something I would prefer to avoid.

    Here's the collision code:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class collideAt : MonoBehaviour
    6. {
    7.     //eventually going to replace this with a collection of all colliders in the scene or something for performance
    8.     public GameObject self, target;
    9.     Collider2D selfCollider, targetCollider;
    10.  
    11.     // Start is called before the first frame update
    12.     void Start()
    13.     {
    14.         //if we have a collider (just to be safe lol)
    15.         if (self != null)
    16.         {
    17.             selfCollider = self.GetComponent<Collider2D>();
    18.         }
    19.         else
    20.         {
    21.             Debug.Log("I don't have a collider");
    22.         }
    23.  
    24.         //if the target has a collider
    25.         if (self != null)
    26.         {
    27.             targetCollider = target.GetComponent<Collider2D>();
    28.         }
    29.         else
    30.         {
    31.             Debug.Log("Target has no collider");
    32.         }
    33.  
    34.  
    35.  
    36.     }
    37.  
    38.     // Update is called once per frame
    39.     void Update()
    40.     {
    41.         if (selfCollider.bounds.Intersects(targetCollider.bounds))
    42.         {
    43.             Debug.Log("Bounds intersecting");
    44.         }
    45.     }
    46.  
    47.     //private void OnTriggerEnter(Collider other)
    48.     //{
    49.     //    Debug.Log("Bounds intersecting");
    50.     //}
    51. }
    52.  
    I reposted this from the physics section because I realized that was not really the right place for this question. Sorry for any confusion that may cause, I'm new to the forum and didn't really know where to ask :|
     
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,497
    You don't want to use 2D physics collision detection but you're using both a TilemapCollider2D and a CompositeCollider2D (not sure why here) which can blend tile-shapes together to make it more efficient. So why are you actually defining such a collider if you're not using it for col-det?

    If you want to do your own col-det then you need to roll your own data. Sounds like you need to add custom-data, probably a simple flag to each tile indicating whether you collide with it or not. You could even use a LayerMask to indicate what the collides with (if anything). If you have a box (bounds) then you can quickly calculate what tiles in the grid this overlaps then check each of those tiles for intersection.

    Alternately, on the assumption you're using physics shapes for sprites, at any position you can get the tile then from the tile get its tile-data then from that the sprite then from that the physics shape. You can generate a bounds from this but you don't want to be doing this JIT, you'd want to bake it into your tile-data. Obviously if you're collision regions are just the full tile then you don't even need this, just need to determine which tiles you overlap and if collision is on for that tile.

    https://docs.unity3d.com/ScriptReference/Tilemaps.Tilemap.GetTile.html
    https://docs.unity3d.com/ScriptReference/Tilemaps.Tilemap.GetTilesBlock.html
    https://docs.unity3d.com/ScriptReference/Tilemaps.TileBase.GetTileData.html
    https://docs.unity3d.com/ScriptReference/Tilemaps.TileData-sprite.html
    https://docs.unity3d.com/ScriptReference/Sprite.GetPhysicsShape.html
    https://docs.unity3d.com/ScriptReference/Sprite.GetPhysicsShapeCount.html

    Still, I don't understand why not use the built-in physics. You can use a simple query like Physics.OverlapBox to determine if a collider exists at the players location. It's easy to determine which tiles overlap a box.
     
  3. MossCairn

    MossCairn

    Joined:
    Mar 14, 2019
    Posts:
    10
    I'm fine with using Rigidbodies so long as I'm only using them for things such as overlap detection, I just don't want them to have an effect on the gameplay.
    The way that I'm writing the collision/movement system, actors handle movement 0.1 units at a time, checking each unit for overlap with anything else. Nothing can move less than 0.1 units, and tiles are 0.8x0.8 units. I'm trying to keep the gameplay and movement tight, so I don't want to use Unity's built-in realistic physics.
    That said, if it's easier to use kinematic rigidbodies, I can try that. I just want to make sure it won't affect the actual movement at all, and I want to keep it simple enough that I can work with it. (I'm no expert, just a gamedev for fun.) I just wasn't sure if using kinematic rigidbodies would have any unforeseen effects on gameplay, and wasn't sure what I needed to use to get the info. I'll test around and see if I can get something working, thanks for the help!
     
  4. MossCairn

    MossCairn

    Joined:
    Mar 14, 2019
    Posts:
    10
    Alright, so I tested a bit using the Physics.OverlapBox and I can't quite figure out how to use it.
    Here's what I added to the code.
    Code (CSharp):
    1. void Update()
    2.     {
    3.         //if (selfCollider.bounds.Intersects(targetCollider.bounds))
    4.         //{
    5.         //    Debug.Log("Bounds intersecting");
    6.         //}
    7.         bool collisionTest = Physics2D.OverlapBox(self.transform.position, new Vector2(0.6f, 1.3f), 0);
    8.         Debug.Log(self.transform.position + " — " + collisionTest);
    9.     }
    It doesn't seem to be doing anything, it's just outputting true. I think I set it up right...?
     
  5. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,497
    I didn't suggest you needed to use Rigidbodies at all. I was questioning why you're using colliders but then don't want to use physics queries. This means you're using colliders as a way of just defining regions which is silly wasteful being as so far you're only describing using box/box intersection tests.

    Here's the docs showing the arguments to use. If it's returning true then the box overlaps the position; this is about all I can say/see from the above.
     
  6. MossCairn

    MossCairn

    Joined:
    Mar 14, 2019
    Posts:
    10
    Ah, ok, I assumed physics was referring to the full 2d physics engine, using rigidbodies and stuff. My bad, I didn't really think that physics referred to more outside of that.
    It turns out I had forgotten to remove the box collider from the player, hence the constant 'true' output. I had assumed you need to use it in conjunction with collider components. Am I supposed to use it without adding collider components in the inspector? Or do I need to make some additional code to tell it to ignore its own collider?
    I'm also having the same problem I was having at the start–the player outputs true when in the bounds of the tilemap, and false when outside. It's still having trouble picking up individual tiles, and I'm still unsure as to why.
     
    Last edited: Oct 5, 2019
  7. MossCairn

    MossCairn

    Joined:
    Mar 14, 2019
    Posts:
    10
    Update: The player was colliding with themself and a wierd hitbox that somehow got tossed onto a gui compnent. Everything's working fine now and I feel like an idiot .–.
     
    MelvMay and LiterallyJeff like this.
  8. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    Welcome to game development :D
     
    almostgiants likes this.
  9. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,497
    It happens. `Note that if you go into the 'project settings > physics 2d > gizmos' you can ask to always show colliders and even show contact arrows too. This can help when you're getting unexpected collision/query results.
     
    MossCairn likes this.