- Home /
How to detect color of different parts of a sprite in 2D game, upon collision?
Hello everybody,
I am tying to put together a 2D game project, part of which requires me to sense the color of a sprite, when it makes contact with the player-controlled object. However, some of the objects will have multiple colors, such as the object in the included picture.
This sprite can be coming towards the player's object, from any angle or position onscreen. It will ALSO be rotating as it is approaching the player. What I would like to know is if there is a good way to detect what side it collides with the player on (whether the red, green, or blue side is touching the player's piece when they make contact). I have already looked into using three different Edge Colliders (one for each third section) but soon found out that there would be no way to differentiate them. I am currently trying a solution that involves me calculating the angle that each colors has within the circle, the circle's starting rotation, angle in respect to the player, and then the angle when colliding, and trying to figure out what the color must be based on math and angles. Also, to be clear, the player's controlled object does NOT change position onscreen, it is always in the exact center. However, is there another solution that might work to this, that is perhaps more simple and elegant? Thank you in advance for all of your help!
Answer by Glurth · Oct 23, 2015 at 06:59 AM
Why not make an empty parent object, then give it three Wedges as children?
Then, each wedge can have it's own EdgeCollider, and react to player contact differently in custom RedWedge,BludeWedge, and GreenWedge scripts.
You mentioned you used three EdgeColliders; as long as they are attached to three separate GameObjects, you can easily differentiate them.
Glurth's solution is the simplest, and fastest way I could imagine. The only other way I know that you can start looking at individual pixel values is to start coding custom shaders--and somehow link those shaders to coded physics--which seems slow and cpu/gpu heavy.
If you have a sprite with complicated geometry--the multiple collider solution might get tricky and complicated--but even still--I don't think a sprite with 10 colliders is going to affect the performance of the game as long as there aren't hundreds of them on the screen.
The solution you mentioned in your question--the math to calculate what part of the collider is being hit is also possible--there is a variable you can access from a collision that gives the point of impact in global space--and from there it would be a matter of figuring out where that point is compared to your sprite and its local rotation/position.
http://docs.unity3d.com/ScriptReference/Collision-contacts.html
Here's a reference to 'contact points' in an OnCollisionEnter(collision) "Collision" returned variable from a physics collision between 2 colliders.
Alternatively--you could RayCast from the playerController--maybe 12 in set rotations--e.g. like the hours of a clock face--which won't be effective at long ranges--but within 1 unit of distance--12 should be more than enough to detect the collider of the 3-colored sprite.
It will probably hit 2-3 rays depending on the sprites size so you'd have to choose the RayCast with the shortest distance before contact and the RayCast function has a built in 'contact' point variable as well.
This is fairly straight-forward--but gets complicated when calculating where on the sprite it hit--e.g. If you had a square ins$$anonymous$$d of a circle and the perimeter of the square was a series of 'pixels.' A 10x10 pixel sprite would mean each pixel is .1 unit of the transforms scale--assu$$anonymous$$g the transform is 1,1,1. The perimeter pixels would have to be stored in an array with their color, and position and every time the RayCast hit point of contact is made--find out where that point of contact is in the array of pixels--which is dependent on the transforms rotation etc. This would work--but it's way complex and would be time-consu$$anonymous$$g to implement. I wouldn't worry about the math way, and look for the simplest way to solve a problem--which is Glurth's collider answer.
I don't know your full idea or vision of what you're attempting to accomplish in the long-run--but based on your current question. I highly recommend @Glurth 's Answer.
Thank you both for your help, @Glurth and @robcbryant :)
Your answer
![](https://koobas.hobune.stream/wayback/20220612042326im_/https://answers.unity.com/themes/thub/images/avi.jpg)