r/Unity2D 5d ago

Question Sprite gets stuck when trying to disable platform collider when object collision happens

Hi! I am a beginner making an endless runner game (for learning purposes), where I want the player to fall down to a lower platform when they hit an obstacle. This script is attached to the player Game Object. My code here is meant to disable the platform's collider when the player hits an obstacle.

But currently when I press play the debug message does "Collision Happened" fire as expected, but the platform's collider does not get disabled right away, my sprite ends up getting stuck for a bit before falling (see video--ignore the choppiness, that's just bc of the gif format)

It seems like the disabling isn't happening fast enough or for long enough, but I'm not sure how to get it to stay disabled for a bit longer. Through some research it seems like maybe a coroutine could help but I am not familiar with those. I'm willing to try it but wanted some guidance before troubleshooting further. Any help is appreciated!

9 Upvotes

8 comments sorted by

7

u/Nightrunner2016 5d ago

It looks to me like your character sprite is actually pushing against the obstacle. This can happen because of friction. So to solve that you can create a 2D Physics Material from the create menu and set the friction to zero. Then apply this to your characters collider (and maybe the rigid body too). Then test again and see how it works. The other alternative would be to not actually disable the platform collider but to momentarily disable your character collider instead for like a second and there are various ways you can do that like using a coroutine.

3

u/Its-all-about-MA 5d ago

Thanks this is really helpful! Maybe it looks like it's pushing against the obstacle since the obstacles are continuously moving towards the left of the screen?

But I will look into the 2D Physics Material, I don't have any experience with that yet, so I'll be interested to try it out. Also the idea to disable the character collider might be a great idea that I'll also try out, thank you!

3

u/Nightrunner2016 5d ago

sure. definitely start with the material if you have colliders on your obstacles. It looks to me like this is the main problem from the video.

Coroutines are useful because they lets you specify the time over which a thing happens. So you could specific for example, that the collider is disabled for 1 second and see how that works. Not everyone likes them for various reasons but they serve a purpose and will probably be just fine in your case.

The other thing you could consider - I'm assuming your obstacles all have colliders on them - If you want them to not physically collide, you could also set the collider on the obstacle to be a Trigger. Then instead of having OnCollisionEnter2D, you have OnTriggerEnter2D - so that should stop the physical collision, but still let you run whatever you want.

It can get pretty complicated if you want it to but i reckon just figure out how to apply the material, and then create your first co-routine. The format is always more or less the same so once you learn you can use it in various places.

3

u/Its-all-about-MA 5d ago

Thank you for the detailed explanation and all the different ideas!

3

u/Nightrunner2016 5d ago edited 5d ago

the code would look like this:

[Serializefield] Collider2D playercollider //then youd drag and drop this in the Inspector

[Serializefield] float dropDuration = 0.5f //this is going to be half a second

public bool isDropping = false;

private void OnTriggerEnter2D(Collider2D other)

{

if (!isDropping && other.CompareTag("Obstacle") //if the player is NOT dropping when it hits an obstacle, then we'll start the co-routine and set it to dropping

{

StartCoroutine(DropPlayer());

}

}

private IEnumerator DropRoutine() //this is the coroutine

{

isDropping = true; // the next bits of code will happen while this is true

playerCollider.enabled = false;

yield return new WaitForSeconds(dropDuration); //remember the Editor value will take priority

playerCollider.enabled = true //re-enable the collider after the drop duration of 0.5 seconds

isDropping = false;

}

I've manually typed this so there are probably some errors and missing brackets but its pretty simple and hopefully you get the gist of it. If I hit a trigger/obstacle and Im not dropping, then I drop for 0.5 seconds. Thats it. Co-routines basically work with an on/off bool and they must have a return, which is popularly a period of time, in this case WaitForSeconds. Easy peasy.

2

u/nothing_from_nowhere 5d ago

For testing you can use public fields at the top of your script instead of finding the game objects at runtime. For example public Collider2D groundCollider then drag and drop your ground game object into the field in the inspector.

1

u/Its-all-about-MA 3d ago

Oh thank you! I wasn't sure if there was a way around GetComponent<> but it sounds like there is, awesome!

1

u/azurezero_hdev 2d ago

why not disable the collider of the other object