Collision with ground (Help)

Hello everybody!

I’m have been working with Unity for the past few months but, I can’t seem to hammer this issue out.

I find myself with a bit of a bizarre issue. I’m currently working on a "2.5"d platformer game and using the Physics engine with Unity for all my movements. I’m having issues checking whether if my player is on the ground on not. I have tried using (and combinations of) Physics.Raycasts and some other tricks and checking normals (i.e. on a collision checking if all the normals are pointing directly vertical). My issue comes especially when I have my player sitting directly beside a wall jumping where for some reason the logic follows thinking I am still on the ground when I jump midair and then go near a wall (yet my raycast doesn’t extend that far on the left and right regions of the bounding box). I have zeroed out the possibility of it being one vector cancelling out and extending the vertical velocity.

Can anybody point me to a good tutorial or code on checking if the player is on the ground? Or any tips in regard to this? I will note once again I am using the Unity Physics engine.

Thank you very much!

Have a beautiful day!

Dan :slight_smile:

Two suggestions. First, look at the FPS Walker script that is included in the stock assets. That has a check for being on the ground. Don’t remember what they do to cehck, though.

Second, you could always put the terrain on it’s own layer, and on the player object, in the OnCollisionEnter() function, do a check to see if the player is colliding with the terrain layer.

The FPSWalker script is using a CharacterController. My player is using only rigidbody and the Physics engine.

I will definitely try the terrain layer technique. That definitely will make sense :).

Thank you very much!

Have a great day!

Dan

Welcome to the forum, PageWizard!

Can you post the code you are using for the raycasts?

//in fixed update. This is at the end of the routine. lastOnGround, and onGround are booleans.

		lastOnGround = onGround;
		onGround = false;

//this is my check for on ground

bool isOnGround()
	{
		//return true;
		//return onGround;
 		return onGround || lastOnGround || (floorCheck());
	}

//this is the floor check. Offset origin is just a little routine I made that offsets from the origin of the player left or right.

bool floorCheck(){
		//could add an epsilon
		bool checkLeft =Physics.Raycast(offsetOrigin(collider.bounds.center,true),new Vector3(0,-1,0),collider.bounds.extents.y+0.1f);
		bool checkMiddle = Physics.Raycast(collider.bounds.center,new Vector3(0,-1,0),collider.bounds.extents.y+0.1f);
		bool checkRight = Physics.Raycast(offsetOrigin(collider.bounds.center,false),new Vector3(0,-1,0),collider.bounds.extents.y+0.1f);
		return checkLeft || checkMiddle || checkRight;
	}

//here is where onGround can be manipulated

void OnCollisionStay( Collision cInfo )
	{
		foreach( ContactPoint cp in cInfo.contacts )
		{
			if( cp.normal == new Vector3( 0, 1, 0 ) )
			{
				onGround = true;
			}
		}
	}
	
	void OnCollisionEnter(Collision cInfo){
		foreach( ContactPoint cp in cInfo.contacts )
		{
			if( cp.normal == new Vector3( 0, 1, 0 ) )
			{
				onGround = true;
			}
		}
		lastCollision = cInfo;
		if(isOnGround())
		{
			jumpLimit = 1;

		}
		else{
			jumpLimit =0;
		}
		
			if( collider.bounds.min.y + collider.bounds.size.y*0.25f >= cInfo.collider.bounds.max.y)
			{
				Vector3 pos = transform.position;
				pos.y = cInfo.collider.bounds.max.y+collider.bounds.extents.y;
				pos.x += (-0.1f)*cInfo.contacts[0].normal.x;
				transform.position = pos;
				//rigidbody.velocity = preCollisionVelocity;
			}		
	}

That is essentially everything I’m using to detect if something is on the ground. I really doubt I would need the floorCheck() routine but, for some odd reason my algorithm doesn’t work when I get rid of that but, introduces a bunch of small glitch cases.

I am attempting a game with similar movement and Used the OnCollisionEnter() function to get a check. but I am wondering if there is a better system than what i have. I am not raycasting so if you know a better way please let me know.

// This is my idea to see if the player is in the air
var isJumping:boolean=false;

function FixedUpdate()
{
// This is the first t est of it just pressing the space bar
if(!isJumping)
		{
		if(Input.GetButtonDown("Jump"))
		{
			this.rigidbody.AddForce(Vector3.up * JumpSpeed);
			isJumping =true;
		}	
		}
}

//Using this function to see if i land on something
function OnCollisionEnter(collisionInfo : Collision)
{
		
		if(Collision)
		{
		isJumping=false;
		}

Is there a better way to use and Do this?