- Home /
Is PolygonCollider2D a legit way to check for mouse clicks in irregular shaped sprites?
Hi there,
I'm new to Unity and always wanted to create a strategy game inspired by Europa Universalis or Hearts of Iron.
So my first goal was to be able to click on a province to select them. For now I illustrate that by changing the color of the province. I'm using a PolygonCollider2D for each province and adjust the collider to the shape of the sprite.
It then looks like this:
And like this for all the 3 provinces(for now):
So selection is working fine, the province graphics are just white so that I can simply set the color when the mouse click happens to be on the province. It's also useful that by using the colliders I can simply zoom in and out and the selection still works fine. Don't bother about the province intersections, there are going to be border graphics overlapping them once I'm coming forward.
My concerns are:
Performance: There are going be several more, over hundred, additional provinces, each of them having one of these colliders. If the mouse is clicked somewhere is every PolygonCollider2D checking in detail for itself or are they first checking for rectangle bounds? There will also be other graphics placed upon the provinces which may need a PolygonCollider2D.
Is this the, so to say, legit way of accomplishing my goal in Unity apart from performance issues? I read something about raycasting and intersecting a ray with a plane(the sprites) but as soon as I put something else on the province I'd also need to check for the color of the pixel as Unity is returning a bunch of intersected pixels(if I unterstood it correctly). With the current approach I just need to adjust the Z coordinate of the graphic on the province by a minimal value so that it's really placed over the province and it is selected instead of the province.
I hope I've been clear enough and if I haven't I'll try to fix it :-)
Thanks for every help!
Answer by CodeElemental · Jun 29, 2016 at 07:45 AM
Regarding the first issue you are safe from performance impact caused by the colliders. Colliders are processed by the physics engine and since you only use them in an "inert" state (they do not actually collide, they do not move etc..) the physics engine will not be burdened. Also, a single raycast for touch/mouse detection does not qualify as 'heavy lifting' for unity.
Regarding the second issue, I would propose "province detection" of some different kind than pixel-type. Maybe create some kind of Script that will hold the relevant data [name, player who controlls it etc etc..] and check the values upon raycasthit. Furthermore, you can separate the province terrain from province objects by placing them in separate layers. You can get the distance to all hit objects and you can process the logic only for the closest one.
Hope this helps you in your journey :)
So I'm save to do it with the colliders.
Also, if I'm getting this right, the colliders and the raycasthit approach don't really differ that much in my case but the collider already does some stuff for me that I therefore don't need to fiddle with. About the layers, it sounds like they're practically behaving the same as if I'm increasing the Z value by this $$anonymous$$imal value what I described. As the value is so small it also doesn't affect the visualization, so no problems in sight for now.
About the script, that's of course going to be written. All the data will be seperate from the visual stuff but I need a simple way to know which province is selected. That's possible now. I'll just connect the SpriteRenderer and the data class in some good way. I'll see about that.
Thank you very much, definitely helped me to get me going :-)
$$anonymous$$y idea was to maybe create a script like
public class Province : $$anonymous$$onoBehaviour
{
public string Name; // The name.
public int Type; // maybe relevant for visual representation
public string PlayerOwner; // relevant for visual representation
}
Which you attach to the province collider. Then you can check the RaycastHit2D for
if (hit.collider.gameObject.layer == Layer$$anonymous$$ask.NameToLayer("Provinces"))
{
// To get the name : hit.collider.gameObject.GetComponent<Province>().Name;
}
Aye, I will look into this RayCastHit2D stuff later in the evening so that I understand it. Thanks!