2D Platformer - Player gets stuck on corners...

Hello everyone!

I tried posting this in UnityAnswers, but Answers seems to be completely broken at the moment, so I hope you guys can help me.

This is my problem:
I’m building a 2D platformer using rigid bodies and Unity physics. Everything seems to be working as intended, except my player frequently gets stuck on the corners of solids. When this happens, you can zoom in real close on the player and the solid, and you can see that the box collider for the player is inside the box collider for the solid by the teeniest tiniest fraction of a unit. When you get stuck, you can’t move at all, which really puts a damper on the whole 2D platforming experience.

Here’s my script: (Javascript)

//************************ 2D Platformer Player Script ************************ //

//Author: 	Aaron Hoffman (Zanzindorf)
//Date:		January 2, 2013

// NOTE: Attach this script to default shape like a cube.

//Control keys
var jumpKey: KeyCode;	
var leftKey: KeyCode;
var rightKey: KeyCode;

//Raycast information
var hit: RaycastHit;	

//Jumping
private var maxJumpPower: float = 150;		//Max charged power of a jump
public var jumpPower: float 	= 0;		//Current power of jump
private var jumpChargeRate: int = 40;		//Rate at which player charges a jump

//Movement
private var moveForce: float 	= 0;		//Force applied to player object when walking (Acceleration)
private var maxMoveSpeed: float = 20;		//Max speed of the layer
private var groundSpeed: float = 60;
private var airSpeed: float = 3;

//Initialize values and physics components
function Start () {
	gameObject.AddComponent(Rigidbody);
	rigidbody.constraints = RigidbodyConstraints.FreezePositionZ | RigidbodyConstraints.FreezeRotation;
	Physics.minPenetrationForPenalty = 0.00001;
	Physics.bounceThreshold = 0;
	jumpKey = KeyCode.Space;
	leftKey = KeyCode.LeftArrow;
	rightKey = KeyCode.RightArrow;
}

function FixedUpdate() {

		/////////////// Jumping ///////////////
	
		if (Physics.Raycast(transform.position, Vector3(0,-1,0), hit, transform.localScale.y))	//Make sure player is standing on ground
		{
			if (Input.GetKey(jumpKey)  rigidbody.velocity.y >= 0) 	//Charge jump if key is pressed and limit is not reached
			{
				rigidbody.AddForce(Vector3(0,maxJumpPower,0));
			}
			
			moveForce = groundSpeed;
		}
		else
		{
			moveForce = airSpeed;
			
			if (!Input.GetKey(jumpKey)  rigidbody.velocity.y > 0)
			{
				rigidbody.AddForce(Vector3(0, -50,0));
			}
		}
		
		/////////////// Movement ///////////////
			
		if (rigidbody.velocity.x < maxMoveSpeed  Input.GetKey(rightKey)  !Physics.Raycast(transform.position, Vector3(1,0,0), hit, 1))
		{
			rigidbody.AddForce(Vector3(moveForce,0,0));
		}
		
		if (rigidbody.velocity.x > -maxMoveSpeed  Input.GetKey(leftKey)  !Physics.Raycast(transform.position, Vector3(-1,0,0), hit, 1))
		{
			rigidbody.AddForce(Vector3(-moveForce,0,0));
		}
}

I’m using Addforce for my main mode of moving the player. I’ve tried adding a function that detects if the player is inside a solid using the OnCollisionStay function, but that function seems to trigger even if the player collider is touching another collider. I need it to trigger only when the player collider is inside another collider.

I can’t figure out a way to do this. I’ve tried making a second collider on the player that’s a fraction smaller than its default box collider, but again, the small distance that the player is getting stuck inside other colliders is so small, it’s impossible to shrink the secondary collider down precisely enough to rule out all probability of getting stuck.

Screen Capture of player collider (top box) getting stuck inside a solid (bottom block):

In the image, the player is stuck relitively far into the solid. Most of the time, the distance into the solid is a lot less, but it’s hard to recreate.

What I’ve already tried:

  • Adjusting the bounceThreshold - No effect regardless of what value I tried.
  • Adjusting the penitrationThreshhold -Much of the same.
  • Rigging up a slightly smaller collider which pushes the player out when triggered - Couldn’t re-size second collider precisely enough to rule out any chance of getting stuck.
  • Screaming really loud - No help, but it felt good.

If you have ideas, help would be muchly loved.

Thanks, and have a nice day,
Zanzindorf

Try to increase collider thickness, if thats not working use a diffrent collider mesh for your player e.g. a capsule collider.

Regards BPR

Hmmm… What exactly do you mean by thickness? Do you mean increase the Z scale? I tried that but no effect.

I also tried changing the box collider to a capsule collider like you suggested. With the capsule, I’m still getting some strange results. The player will still get stuck, but instead of being permanently stuck, the player will slowly roll off the solid, which is still kind of annoying since you can’t move until you have rolled off completely.

No i don’t mean to scale the collider, there should be a variable that sets the thickness of the collider, i guess it was an option for a character controller, use a character controller! As you noticed correctly the colliders of the platform and player get locked otherwise.

PS: The variable name is skin width:

Regards BPR

I’ll give that a try. I was avoiding using the character controller because it just doesn’t fit well with the game mechanics I have planned. I was really hoping to get this script working.

Regardless of what the best option for creating the player is, I keep running into this problem with other objects, such as flying monsters and projectiles. For objects like those, there is no way for me to use the character controller to keep them from getting stuck in walls.

I would like to figure out what’s causing this error so that I don’t run into it again with other objects. Using a character controller will fix the player no doubt, but it won’t solve this reoccurring problem for other object that I move using AddForce, which I have hear is the only way to move a rigidbody without having to calculate your own collision detection for avoiding solids.

Hm maybe this could help you:

Reducing scale of the entire secene:
http://gamedev.stackexchange.com/questions/24592/collision-intepenetration-and-objects-getting-stuck-unity

And if you are using gravity try to ajust “Min Penetration For Penalty” and “Solver Iteration Count”:

Regards BPR

(hideous = zanzindorf; not sure why my username change all the sudden)

I believe I have found the issue. It had less to do with Unity Physics than it did with my own stupidity. My character is supposed to accelerate slower horizontally when airborne. To test if the player is airborne, I used a raycast.

However, the raycast projects from the center of the character. When I hit a corner, my character reads that it is airborne even though its still on the ground because the raycast is missing the solid. This causes the player to move with less force. In combination with ground friction, it appears he is not moving at all.

I fixed it by moving the raycast to run parallel to the player base. Doh!

Thank you BPR for your help. I learned a lot about Unity Physics in case I get in trouble again.
Have a super day!

1 Like