0
\$\begingroup\$

I have a sprite which has a transparent area in it. The non-transparent area is a free-form graphic (red). I would like to create a box collider around it (yellow), but ignoring the transparent area.

enter image description here

Some notes to the image above:

  • Left: This is what happens, if I apply a PolygonCollider2D. The yellow line represents the area covered by the PolygonCollider2D. This is not what I want.
  • Middle: This is what happens, if I apply a BoxCollider2D. The yellow line represents the area covered by the BoxCollider2D. This is also not what I want, as it includes the transparent area of the sprite.
  • Right: This is what I want: Have a BoxCollider2D outside my free-form graphic.

Here's how I currently load my sprite data into the game during runtime:

  • My sprites are located in the /Assets/Resources/SceneData/... folder structure of my project. The graphics are stored as .png files.

  • When loading a level, I load the required graphics as sprites like this:

    var sprite = Resources.Load<Sprite>("SceneData/AfternoonAtTheBeach/DragAndDrop/Graphics/Level1/ElephantWithIceCream");

"ElephantWithIceCream" is the .png file (Resource.Load wants me to refer to this file without file extension)

  • After that, I create a new game object and attach a SpriteRenderer component to it. The sprite is assigned to the SpriteRenderer by setting the sprite attribute of the SpriteRenderer component.

My first thought on how to solve my problem was to do something like this:

  • Create a PolygonCollider2D and try to convert it into a BoxCollider2D. But I was not able to find code examples on how to do this.

After that, I thought of trying it to do like this:

  1. Create a PolygonCollider2D and try to extract some useful information out of it (such as bounds, center, extents, etc...).
  2. Delete the PolygonCollider2D and create a BoxCollider2D. Use the previously extracted info to create the BoxCollider2D.

But I fail doing so. I am also a bit confused as sometimes they refer to world space or local space. Does anyone have a working recipe for doing something like this? I do not really understand how to work with center, bounds and extents. If there is any better way of doing this, I am highly interested. Thanks a lot for your help!

\$\endgroup\$
11
  • \$\begingroup\$ Is there a reason why you cannot modify the BoxCollider from "Edit Collider" in the Inspector window? From there you should be able to just manually modify the size of the colliders. \$\endgroup\$
    – FSic
    Sep 23, 2019 at 7:22
  • \$\begingroup\$ @FSic: Yes, I need to do this programmatically during runtime. \$\endgroup\$ Sep 23, 2019 at 7:24
  • \$\begingroup\$ you need to make your own collision system. for that. you can put multiple colliders on each side \$\endgroup\$
    – virtouso
    Sep 23, 2019 at 8:57
  • 1
    \$\begingroup\$ "I need to do this programmatically during runtime" — so this means you are loading or generating new sprites at runtime that you've never seen before at edit time? Can you show us how you generate/load those sprites? It's possible we can capture this bounds information as part of that process, potentially more cheaply than extracting it after the fact. \$\endgroup\$
    – DMGregory
    Sep 23, 2019 at 11:43
  • 1
    \$\begingroup\$ It looks like all your sprites exist at edit time, in order to be able to load them from resources (which you should avoid doing — Unity has better options). So you should be able to set up these bounds by hand in a prefab or ScriptableObject and save yourself any runtime image analysis. \$\endgroup\$
    – DMGregory
    Sep 24, 2019 at 10:04

3 Answers 3

1
\$\begingroup\$

I would recommend using photoshop PSB importer package. You design your sprites in photoshop/illustrator, position them properly there, and when imported into unity, the resulting sprites will be cropped to size of the non-transparent area of the layers by default, just as you've shown above. The result will also keep relative positions perfectly.

The default box-collider will be exactly what you have drawn above.

\$\endgroup\$
0
\$\begingroup\$

Posting late to the party just to provide my 2 cents on this matter.

As @DMGregory has mentioned, unless you have some absurd number of sprites to generate prefabs from (in which case, automation may be something worth investing in), doing it manually could be the way to go.

That said, I've run into a similar issue and I wanted to share some advice that really helped me come up with a solution for my project.

Invest some time / thought into how your asset pipeline is going to work. This involves everything from:

  1. where are your sprites getting created (Photoshop, Aesprite)?
  2. how are you exporting them (file format, etc...)?
  3. how are you bringing them into Unity (folder structure / organization)?
  4. what is the structure of the prefabs that display these sprites?

I'm not familiar with your project, but maybe it turns out you don't need those transparencies in the first place. So maybe your issue resides within point 2 above. Maybe you might choose to export your images as tight as possible, so then you can generate colliders directly to the bounds of the sprite (if you're using the sprite renderer component, check out SpriteRenderer.Bounds).

Maybe you do need those transparencies though. While you may have to generate these colliders by hand, you can still alleviate some pain points by defining a process for how to make your prefabs.

For instance, if you have some sprites that have transparencies, can you use the sprite editor to auto slice, and then generate your collider using the sliced image?

This is a bit off topic, but I've also found that defining some rules about each sprite having a fixed border size can really help, especially when it comes to playing animations. It can be really useful to define each sprite has having their center of the free form shape be at the center of the entire image (or some other fixed point that is consistent from sprite to sprite).

Hope that helps!

\$\endgroup\$
2
  • \$\begingroup\$ Thank you very much for your response. The real reason I was considering these transparent areas was to simplify sprite placement in the scene, where I have to precisely align sprites. Having all sprites of the same site (but with transparent regions in it) allows me to use the same coordinate for sprite placement, but the sprites showing up in different locations (imagine a puzzle game for example, where the size of a single sprite is as large as the puzzle area, but with transparency in it). Because of PNG compression algorithms, file size remains almost the same (even with transparency). \$\endgroup\$ Nov 19, 2019 at 11:23
  • \$\begingroup\$ "Because of PNG compression algorithms, file size remains almost the same" Do keep in mind that the file is no longer in PNG format when it gets uploaded to video memory and used for rendering. It needs to be unpacked to a format with a constant bit rate for efficient sampling, and that means you pay for every extra bit of transparency you add. \$\endgroup\$
    – DMGregory
    Jun 26, 2022 at 10:13
0
\$\begingroup\$

https://docs.unity3d.com/ScriptReference/MeshCollider.html

as your mesh-collider is generated automatically, based on above reference, you can get the list of vertices and also bounds of collider you have.

just check the Bigget X,Y and Lowest X,Y to set bounds of your 2d box-collider.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .