- Home /
Prefab Collider2D not Recognized as Raycast Collider
Hello everyone :) Here's the situation:
I have a baddy prefab which has two collider components: a simple CapsuleCollider2D used for physics, and a trigger PolygonCollider2D used only for mouse point collisions.
The PolygonCollider2D is updated through an attached script (Baddy.cs) only when needed using:
if(this.gameObject.GetComponent<PolygonCollider2D>()!=null){
Destroy(this.gameObject.GetComponent<PolygonCollider2D>());
}
this.gameObject.AddComponent<PolygonCollider2D>();
this.gameObject.GetComponent<PolygonCollider2D>().isTrigger=true;
Yes, this is poor practice, but it get's the job done. It works perfectly: in the scene view of the game I can pause and see that there is indeed a polygon collider on our baddy prefab.
In another attached script (CollisionHandler.cs) we check for a mouse press on our baddy:
if(MousePress()){
hit=Physics2D.Raycast(level.mousePoint, Vector2.zero, 0f);
if(hit&&hit.collider==this.gameObject.GetComponent<PolygonCollider2D>()){
print("baddy mousePress");
}
}
However hit.collider==this.gameObject.GetComponent<PolygonCollider2D>()
turns out false, even though I could print both hit.collider
and this.gameObject.GetComponent<PolygonCollider2D>()
immediately before hand in our if(MousePress()) and have them both defined as:
D_Prefab(Clone) (UnityEngine.PolygonCollider2D)
They couldn't be different PolygonColliders because there can only be one at a time, since our Baddy script removes and creates the PolygonCollider simultaneously.
Any ideas what could be going wrong?
Answer by jjcrawley · Mar 17, 2017 at 02:37 AM
Your raycast isn't casting. Well, it is, just not very far. Let me explain, the Physics2D Raycast takes in an origin, a direction, a distance. and a few other titbits. You've written it like this:
hit=Physics2D.Raycast(level.mousePoint, Vector2.zero, 0f);
Your origin is fine, your direction and distance on the other hand are not. You haven't specified a direction and your casting distance is 0. As a consequence, your ray won't hit anything because it doesn't know which direction to go and it's length is 0, by default distance is Mathf.Infinity. So the cast can't hit anything.
You need to decide which direction to fire in and how far, if you want to specify a distance. This should fix that issue. A few potential issues that may arise afterwards though are detecting the right collider. If the ray hits any collider, it will immediately return that collider, regardless of which collider it is.
Probably the better, and more useful, solution is to make use of a layer mask. This approach involves moving the enemies onto a separate physics layer, so when you do the raycast, you only cast on that layer. A layermask is one of the extra titbits that you can pass to the raycast function:
hit = Physics2D.Raycast(level.mousePoint, Vector2.Right, 20, LayerMask.GetMask("MyEnemyLayer"));
That should fix any issues that you may run into. The direction, distance and layermask are up to you. Have a peak at the LayerMask documentation for info about how to use it.
Also, make sure that you setup the Physics2D Manager to query triggers, if you don't, the raycast will fire but may ignore the triggers.
Something else that you may want to look into is the mouse down event that Monobehaviours can subscribe to. This is fired whenever the user clicks on a collider, or GUIElement. You don't have to worry about raycasting yourself then, and you don't have to check which collider was hit. If this event is raised on a baddy component, you clicked on a baddy.
Hopefully this helps.
Unfortunately, this did not resolve the issue. I tried changing the line to hit=Physics2D.Raycast(level.mousePoint, Vector2.right, .5f);
and even hit=Physics2D.Raycast(level.mousePoint, Vector3.forward, 1f);
. (By the way, the code was working fine when I only created the baddy polygonCollider once on a start function, but after I tried updating the collider through the update function it refuses to work). Also, the issue is not with clicking on the capsuleCollider on accident, since I can click outside of it specifically on the polygonCollider and it still won't work.
Don't 'update' the collider, especially if by update you mean destroy and add a new one each update. The physics engine won't have time to check for any ray collisions, as a consequence, it will return the wrong collider info. You only attach in start or awake, and this is done only once. You shouldn't have to constantly attach new components. It may be worth actually adding in the polygon collider to the baddy prefab, this will give you more control over the shape of the click zone, very useful from a design perspective. You won't have to constantly attach a new one in start either. When the start method is called you can cache a reference to the component and check that each update, much safer and more efficient. Something along these lines:
PolygonCollider2D myCollider;
void Start()
{
myCollider = GetComponent<PolygonCollider2D>();
//any other start stuff
}
Then for your hit check becomes:
if(hit.collider == myCollider)
{
//do a thing
}
@jjcrawley thanks for your detailed responses. I was afraid of that, you see, because putting new polygonColliders throughout all of my baddy animations would take a long time. There really isn't a way to do this by code? If there is no way to achieve this at run time, what does this line mean? %|971109959_2|%
Don't know, the comment code thing was messing around. I think it was supposed to be 'any other start stuff', looks okay on my end just a glitch. You shouldn't have to add polygon colliders to all your baddy animations, just the prefab. Unity uses property paths for their animation stuff, this is just the name of the variable and any other bits and pieces that they need to update that variable at runtime. As a consequence, adding in a new collider to the prefab shouldn't mean that you have to redo all your animations, especially if you're just using sprites for animation. It should, theoretically, just work. Try it and see.
Unfortunately, with animations, the polygonCollider component won't update on its own through the animations, it will only retain the first sprites polygonCollider shape for the animation.
If you wanted to change its shape then yes, you'll have to animate the collider by hand. Why not use a box collider? The polygon collider would be more expensive to calculate intersections for at runtime, and the box collider should be accurate enough for your clicking needs. Of course though, it won't match the shape of your baddies as perfectly, but most games wouldn't require that level of precision for simple clicks. On top of that, you'd only have to animate the height and width of the collider. When compared to a polygon collider it would be much simpler. Just a thought.
@jjcrawley, you would definitely be right in most cases, but unfortunately I definitely need this to be precise. From your experience, do you believe that creating polygonColliders in the animations would bog down the system? Also, can you think of any other methods to achieve what we're trying to do? $$anonymous$$any thanks
For future reference, Physics2D.RaycastAll with a layer$$anonymous$$ask helped resolved this situation.
Answer by Commoble · Mar 16, 2017 at 09:28 PM
First thing I can see is that your hit check reads as false if it doesn't hit the polygon collider, but a raycast will stop at the first collider it hits, so it'll also returns false if it hits some other collider, including your capsule collider on the same object.
If I understand what you're saying, shouldn't the hitTest only consider polygonColliders on the baddy since we're checking hit.collider==this.gameObject.GetComponent<PolygonCollider2D>()
Your raycast can potentially hit ANY collider that exists at that point in space, regardless of which object it's on or what type of collider it is. If the collider it hits is NOT your object's polygon collider, then your if statement will be false.
If I had just put hit==this.gameObject
then it would consider any type of attached collider, right?
hit.collider.gameObject == this.gameObject
, but yes
Oops yes good call hit.collider.gameObject
@Commoble But still the question remains what is wrong with the code? Shouldn't this work perfectly then since we decided that the code searches for a collision with only the baddy's polygonCollider as intended?
By the way the capsuleCollider is not the real issue, I can click outside the capsuleCollider on the PolygonCollider and it still won't work @Commoble
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Need a simple car physics script working on unity 5? 1 Answer
why Raycast2D doesn't work properly? 0 Answers
Clamping movement causes jittering 1 Answer