Collision 'pass through' from the bottom, solid from the top

Hey all,

Having an issue creating platforms that are passable when the player is moving up and solid when the player is moving down. I’m using the trigger method to disable the collider and that is working perfectly, 99 percent of the time. That 1 percent is killing me. Basically, every once in a while, neither OnTriggerExit nor OnCollisionExit is called, thus causing my problem and I’m working on trying to find a solution to this.

Info: All platforms are set to triggers initially. That would make it so you just fell through them no matter what. On trigger enter, I check the player’s velocity and if they’re moving down, we turn the trigger off thus activating the collider and thus making the platform solid. On trigger exit, I make sure to turn it back to a trigger and we’re all set, right? Well every once in a while when I graze a platform while falling, it seems, I’ll get OnTriggerEnter to occur as well as a collisionenter (which means it properly turned off the trigger and hit the collider) but no trigger or collision exit… :confused: When this happens, I then have a platform sitting in a solid state, so if I fly upward into it, the player will hit it as a solid object, thus breaking my game. I can’t set the trigger to true once I’ve detected this collision, as the momentum of the player has already stopped and it does me no good. For a better explanation of everything, see below:

Here’s the logic.

function OnTriggerEnter(acollider : Collider) {
	// DEBUG 
	// print("player entered TRIGGER: " + acollider.gameObject.name);
	goc = acollider.gameObject.GetComponent(Collider);
	if (myvelocity <= 0){ // If the player is falling
		//make platform solid
		goc.collider.isTrigger = false;
	}
	if(myvelocity > 0){
		//make platform passable
		goc.collider.isTrigger = true;
	}
}

function OnTriggerExit(acollider : Collider){
	// DEBUG print("platform trigger exited successfully");
	goc = acollider.gameObject.GetComponent(Collider);
	goc.collider.isTrigger = true;
}

function OnCollisionEnter(acollision: Collision){
 	// DEBUG 
 	/*for (var contact : ContactPoint in acollision.contacts) {
        print(contact.thisCollider.name + " entered a COLLISION " + contact.otherCollider.name + "at point " +  contact.point + "cn" + contact.normal);
        Debug.DrawRay(contact.point, contact.normal*100, Color.white);
 	}*/
 	
 	// Here's where I found the problem happens, OH NO!
 	var contact : ContactPoint = acollision.contacts[0];
 	if(myvelocity > 0) {
 		contact.otherCollider.isTrigger = true; // this doesnt help now, the player momentum has already been stopped
 		print("This is where the problem occurs. We're moving up and actually HIT a solid platform. Fail.");
	}
}

function OnCollisionExit(acollision : Collision){
	// DEBUG 
	// print("platform collision left successfully: " + acollision.gameObject.name);
	goc = acollision.gameObject.GetComponent(Collider);
	if(acollision.gameObject.name != "wallleft"  acollision.gameObject.name != "wallright"){
		goc.collider.isTrigger = true;
	}
}

Can you think of a way to solve this? I guess I could just run through an array of all of the platforms and make them a trigger every frame to fix any stragglers caused by this issue, but that would be horribly wasteful.

I seemed to have solved it by caching the velocity and angularvelocity of the last frame. If conditions occur to make one of those ‘bad’ collisions, restore the values to keep the player moving as if nothing happened.