Search Unity

Changing BoxCollider2D size to match sprite bounds at runtime

Discussion in '2D' started by Architekt, Sep 12, 2014.

  1. Architekt

    Architekt

    Joined:
    Jul 6, 2014
    Posts:
    7
    I have an object that's pooled which I recycle. When I recycle it and add it to the game, I sometimes change its sprite. The problem is, the BoxCollider2D I have attached to it stays the same size. I would like to make its size match the bounds of the sprite, like what happens if I just create a brand new game object in the editor, plop a sprite on it, and then plop a BoxCollider2D on top of that.

    My issue is that I don't quite know what the numbers mean in regards to Box Collider's size field. The docs say it's the width/height of the rectangle, but I'm not sure in what units. My sprite certainly isn't 1.74x0.31 pixels in dimension. So I assume it's a scale of some kind. Anyway, my question is: how do I compute the values to put in this size field such that it matches the bounds of the sprite, at run time? Thanks.
     
    Attos likes this.
  2. Kawaburd

    Kawaburd

    Joined:
    Jul 22, 2013
    Posts:
    16
    Truth be told I don't know either, BUT I know a workaround.

    Code (CSharp):
    1. Vector2 S = gameObject.GetComponent<SpriteRenderer>().sprite.bounds.size;
    2.         gameObject.GetComponent<BoxCollider2D>().size = S;
    3.         gameObject.GetComponent<BoxCollider2D>().center = new Vector2 ((S.x / 2), 0);
    I use this for melee attacks in an action platformer currently. the bounds.size vector will give you the right numbers in scale... I think. (Test this though, I have everything set to 1 pixel/unit to help fix tileset clipping problems). Set it Update() it'll match the sprite's bounds every frame, but there's a couple quirks.
    1. Bounds.size measures whatever you defined the sprite as, even if there aren't any visible pixels in like half of it. If you left any blank space (say, using 'grid' to get frames out of a tileset), that's going to be in the collider too.
    2. You might want to define what order scripts run in for this. If this fires off BEFORE the animation code, the collider's always going to be one frame behind the sprite. It's unnoticeable unless your framerate's really low, but something to be aware of.
     
    Attos, drtaikenov, samuel812 and 6 others like this.
  3. Architekt

    Architekt

    Joined:
    Jul 6, 2014
    Posts:
    7
    Awesome, that worked. Thanks!
     
  4. einzweidrei

    einzweidrei

    Joined:
    Jan 19, 2015
    Posts:
    2
    Also, worked for me. Thankx. :)
     
  5. bluelock3

    bluelock3

    Joined:
    May 24, 2015
    Posts:
    2
    well my game object is constantly growing every frame how could i get my boxcollider2d to stay on it (it will also be going in odd directions)
     
  6. stonecompass

    stonecompass

    Joined:
    Aug 5, 2015
    Posts:
    13
    Thanks for the workaround! Worked for me to too!
     
  7. UncleChris

    UncleChris

    Joined:
    May 15, 2014
    Posts:
    2
    It worked for me also, thanks!
     
  8. plangton

    plangton

    Joined:
    Mar 25, 2014
    Posts:
    1
    Here is the code i wrote for my collider to match my sprites.
    the problem with Kawaburd solution is that firstly it doesn't consider the scale to the account and secondly that ".center" is deprecated and honesly modifying it in the latest unity versions is unnecessary



    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [ExecuteInEditMode]
    6. public class ColliderFitSprite : MonoBehaviour
    7. {
    8.     void Awake()
    9.     {
    10.         runInEditMode = true;
    11.     }
    12.  
    13.     void Update()
    14.     {
    15.         var _sprite = FindObjectOfType<SpriteRenderer>();
    16.         var _collider = FindObjectOfType<BoxCollider2D>();
    17.  
    18.         _collider.offset = new Vector2(0, 0);
    19.         _collider.size = new Vector3(_sprite.bounds.size.x / transform.lossyScale.x,
    20.                                      _sprite.bounds.size.y / transform.lossyScale.y,
    21.                                      _sprite.bounds.size.z / transform.lossyScale.z);
    22.     }
    23. }
     
    Last edited: Apr 4, 2018
    tbriz, Favo-Yang and diegoleao like this.
  9. Fraisy

    Fraisy

    Joined:
    Jan 19, 2018
    Posts:
    1
    it works thanks ....
     
  10. duartejuca

    duartejuca

    Joined:
    Aug 23, 2018
    Posts:
    13
    Thanks works fine for me.
    Only thing I have to change was center to offset and maintain zero in x and y.
     
  11. Im_Jest_Faiq

    Im_Jest_Faiq

    Joined:
    May 16, 2021
    Posts:
    5
    This is for BoxCollider2D
    Know any way to make this work for edge collider so that i can have objects IN this object
     
  12. mitaywalle

    mitaywalle

    Joined:
    Jul 1, 2013
    Posts:
    253
    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3.  
    4. [ExecuteInEditMode]
    5. public class BoxCollider2DFitSpriteRenderer : MonoBehaviour
    6. {
    7.     [SerializeField] private Vector2 _sizeOffset;
    8.     [SerializeField] private Vector2 _centerOffset;
    9.     private SpriteRenderer _sprite;
    10.     private BoxCollider2D _collider;
    11.  
    12.     private void Awake()
    13.     {
    14.         runInEditMode = true;
    15.         _sprite = GetComponent<SpriteRenderer>();
    16.         _collider = GetComponent<BoxCollider2D>();
    17.     }
    18.  
    19.     private void Execute()
    20.     {
    21.         if (!_sprite.enabled || !_sprite.gameObject.activeInHierarchy) return;
    22.  
    23.         Vector2 scale = transform.lossyScale;
    24.         Vector2 size = _sprite.bounds.size;
    25.  
    26.         size = new Vector2(size.x / scale.x, size.y / scale.y) + _sizeOffset;
    27.  
    28.         if (size != _collider.size)
    29.         {
    30.             _collider.size = size;
    31.             #if UNITY_EDITOR
    32.             EditorUtility.SetDirty(_collider);
    33.             #endif
    34.         }
    35.  
    36.         Vector2 offset = (Vector2) (_sprite.bounds.center - transform.position) + _centerOffset;
    37.  
    38.         if (offset != _collider.offset)
    39.         {
    40.             _collider.offset = offset;
    41.             #if UNITY_EDITOR
    42.             EditorUtility.SetDirty(_collider);
    43.             #endif
    44.         }
    45.     }
    46.  
    47.     #region Editor
    48.  
    49.      #if UNITY_EDITOR
    50.     private void Update()
    51.     {
    52.         if (Application.isPlaying) return;
    53.  
    54.         Execute();
    55.     }
    56.     #endif
    57.  
    58.   #endregion
    59. }
    60.  
     
    enpiech_unity likes this.