2D: How to detect if a screenposition is within the _not_ transparent region?

Hi,

Using 2D sprites, orthogonal camera.
Q: How to detect if a screenposition is within the not transparent region of a sprite?

Normally I use to detect the object in a screenposition with the following code:

Ray ray = topGameScreen.Camera.ScreenPointToRay(screenPos);

if (Physics.Raycast(ray, out hit))
{
if (hit.collider.gameObject.active)
{
return hit.collider.gameObject;
}
}

Now I am using 2D sprites, and there are transparent parts of the sprite (PNG). Of course the collider attached to the sprite is a BoxCollider, so the ray will detect it :frowning:

My question: What is the correct method to use in this case?
a) Forget about rays? … Is there any other simple way to do this?
b) Use rays and try to use a custom collider? :-(. It sounds a little bit overenginered, not talking about the fact I have no idea how to create a custom collider for a drawing (sprite), and also not talking about, there are many drawings (sprites)

Thx for the answers

There are three main solutions to this.

  1. Instead of using a single box collider, you can attach multiple colliders to your sprites. This is fine if you only need 2 or 3, but could become expensive if the sprites are complex in shape:

Remember, shape colliders (sphere, cube, cylinder?) can be scaled and positioned independently of the gameObject it is attatched to.

  1. You can check the color of the pixel at the point the raycast has hit the sprite. (This is expensive and is not recommended at all). You will need a combination of Texture2D.GetPixel() and RaycastHit.TextureCoord.

  2. Consider using a dedicated 2D framework. These are often paid for packages in the asset store, but there may be some free alternatives around.

You could use any of the shape colliders, it doesn’t have to be a Box collider, or even use multiple colliders as suggested by Alastair.

How accurate you need to be will determine the solution you use. A finger on a touchscreen would be more forgiving than having 2 cog sprites interact for example.

The cog example might need a mesh collider. To create the mesh, you could put the sprite image on a plane in a 3D modelling package, then model the shape you want over the image. Import the model into Unity and drag the mesh onto the field in the mesh collider.

If you use a vector package such as Illustrator to create your sprites, you can export a spline into a 3D modelling package and loft it to create the mesh.

Hi Alastair Callum,

Thx for this excellent detailed answer.
Btw I am using Orthello (free) as 2D framework, It is really great, but I do not noticed any out of the box solution for my problem. Maybe I missed something

Thx again.

No problem, I’ve just been reading through the docs for Orthello, particularly the section about collisions. It says that the framework uses Unity’s collider system for it’s detection.

This being said, you should simply be able to configure your colliders (like I mentioned in option 1, with the tree) in the sprite’s component list and set the sprite to be the required type from the Orthello framework (ie rigidbody/staticbody).

This is purely speculative but that should work, let me know how you get on.

[EDIT] Ok, I’ve been playing around with Orthello on my lunch break. Unfortunately the framework will not pickup more than 1 collider on an object. I’ve tried by having two different colliders on 1 object, and even having a child gameObject with a collider. But it looks like it’s a limitation of the Orthello framework.

So… for now I can’t think of how to resolve a multi-collider solution. Although, it would be possible using the standard Unity physics stuff… but then you loose out on the OT stuff which is kinda important for you.

Although moonjump suggested making your own colliders, I don’t think this will work with the OT framework as it only supports sphere and cube colliders.

The only solution that really remains is to simply manipulate the OTSprite collider to cover as little of the sprite as possible. This depends of course on how important the accuracy of the detection is. Or, you could try the pixel color method…

Hi Alastair Callum,

Very thx for you info.

To share mine:

Orthello not only deletes the multiple colliders, but zeros the center the original BoxCollider (to be exact, uses Pivot center to calculate it, but setting pivot also ofsett the sprite itself, not talking about other side effects.)

So I ended up to create an empty gameObject child for my sprite (“behind it”), and configure it with my multiple colliders. When the original sprite is hitting, then I cast a new ray from the sprite to the direction of the follower collider container.

About the pixel hacking: I confess I tried if first. Unfortunately not all texture types support it, and as I am targeting Android my compressed texture type is RGBA16
which not supports reading pixels.

Wrap it up: I have a working solution with multiple colliders + a workaround for Orthello “automated” collider manipulation

Thx again