protected void MoveInYDirection (bool grounded)
	{
		float slope = 0.0f;
		int slopeCount = -1; 
		bool isClimbing = false;
		bool cantClimbDown = false;
		bool hasHitHead = false;
		int climbCount = 0;
		groundedFeet = 0;
		isClimbingUpOrDown = false;
		
		// Create a copy of character input which we can modify;
		float characterInputY = characterInput.y;
		
		// Ignore input if stunned
		if (stunTimer > 0.0f)
			characterInputY = 0.0f;
		
		// Limit Velocity
		if (velocity.y < (movement.terminalVelocity * (IsSwimming ? (1 - swimming.waterResistance.y) : 1)))
			velocity.y = movement.terminalVelocity * (IsSwimming ? (1 - swimming.waterResistance.y) : 1);
		
		if (IsSwimming && velocity.y > swimming.maxYSpeed) velocity.y = swimming.maxYSpeed;
		
		// Apply velocity
		if ((myParent == null || !myParent.overrideY) && (velocity.y > movement.skinSize || velocity.y * -1 > movement.skinSize)) {
			myTransform.Translate (0.0f, velocity.y * frameTime, 0.0f, Space.World);
		}
		
		if (fallThroughTimer > 0.0f)
			fallThroughTimer -= frameTime;
		
		// Fall/Stop
		bool hasHitFeet = false;
		if ((velocity.y <= 0.0f || startedClimbing) && ledgeDropTimer <= 0.0f) {
			float maxForce = 0.0f;
			GameObject hitGameObject = null;
			float lastHitDistance = -1;
			float lastHitX = 0.0f;
			
			foreach (RaycastCollider2D feetCollider in feetColliders) {
				RaycastHit2D hitFeet = new RaycastHit2D ();
				RaycastHit2D hitLadder = new RaycastHit2D ();
				RaycastHit2D hitGround = new RaycastHit2D ();
				float closest = float.MaxValue;
				float closestLadder = float.MaxValue;
				
				RaycastHit2D[] feetCollisions = feetCollider.GetAllCollision (1 << backgroundLayer | (fallThroughTimer <= 0.0f ? 1 << passThroughLayer : 0) | (climbing.allowClimbing && fallThroughTimer <= 0.0f ? 1 << climableLayer : 0), slopes.slopeLookAhead);						
				// Get closest collision
				foreach (RaycastHit2D collision in feetCollisions) {
					// If we got a ladder also keep reference to ground
					if (collision.collider != null && collision.collider.gameObject.layer == climableLayer) {
						if (collision.fraction * (feetCollider.distance + slopes.slopeLookAhead) < closestLadder) {
							hitLadder = collision;	
							closestLadder = collision.fraction * (feetCollider.distance + slopes.slopeLookAhead);
						}
					} else if (collision.fraction * (feetCollider.distance + slopes.slopeLookAhead) < closest) {
						hitFeet = collision;
						closest = collision.fraction * (feetCollider.distance + slopes.slopeLookAhead);
					}
					if (collision.collider.gameObject.layer != climableLayer)
						groundedFeet++;
				}
				
				// If ladder is closest collider
				if (hitLadder.collider != null && hitFeet.collider != null && hitLadder.fraction * (feetCollider.distance + slopes.slopeLookAhead) < closest) {
					// Only assign ground if its a true hit, not a slope look ahead hit
					if (hitFeet.fraction * (feetCollider.distance + slopes.slopeLookAhead) <= feetCollider.distance && hitFeet.collider.gameObject.layer != climableLayer) {
						hitGround = hitFeet;
						hasHitFeet = true;
					}
					hitFeet = hitLadder;
				}
				
				// If only hitting a ladder
				if (hitLadder.collider != null && hitFeet.collider == null) {
					hitFeet = hitLadder;	
				}
				
				float force = (hitFeet.normal * (feetCollider.distance - (hitFeet.fraction * (feetCollider.distance + slopes.slopeLookAhead)))).y;	
				// Standing on a something that has an action when you stand on it
				if (hitFeet.collider != null) {
					Platform2D platform = hitFeet.collider.gameObject.GetComponent<Platform2D> ();
					if (platform != null && feetCollider.distance >= hitFeet.fraction * (feetCollider.distance + slopes.slopeLookAhead)) {
						platform.DoAction (feetCollider, this);
						Transform parentPlatform = platform.ParentOnStand (this);
						if (parentPlatform != null) {
							// Normal parenting (moving platforms etc)
							myParent = platform;
							if (myTransform.parent != parentPlatform) {
								myTransform.parent = parentPlatform;
							}
							hitGameObject = hitFeet.collider.gameObject;
						}
						// Special case for the top of a ladder
						if (platform is TopStepPlatform2D) {
							hasHitFeet = true;
							maxForce = force;
							hitGameObject = hitLadder.collider.gameObject;
						}
					}
					// Climbing 
					if (climbing.allowClimbing && hitLadder.collider != null && hitLadder.fraction * (feetCollider.distance + slopes.slopeLookAhead) <= feetCollider.distance && jumpButtonTimer <= 0.0f) {
						//bool ladder = hitLadder.collider.gameObject.GetComponent<Ladder>();
						//if (ladder == null) hitLadder.collider.gameObject.GetComponent<Rope>(); // && ladder != null
						climbCount++;
						if (!(myParent is TopStepPlatform2D) && (startedClimbing || (climbing.autoStick && hitGround.collider == null && (dismounting == null || (myParent != null && dismounting != ((Ladder2D)myParent).control)) || characterInputY != 0))) {
							if (climbCount >= climbing.collidersRequired) {
								startedClimbing = true;
								isClimbing = true;
								hasHitFeet = true;
								dismounting = null;
								// Allow platforms to stop us climbing
								if (myParent == null || !myParent.overrideY) {
									if (characterInputY > 0.0f) {
										// Ensure we dont go above step
										maxForce = climbing.speed * frameTime;
										if (maxForce > force)
											maxForce = force;
										isClimbingUpOrDown = true;
									} else if (!cantClimbDown && characterInputY < 0.0f) {
										maxForce = climbing.speed * frameTime * -1;
										// Ensure we don't go into ground
										isClimbingUpOrDown = true;
										if (hitGround.collider != null) {
											float groundForce = (hitGround.normal * (feetCollider.distance - hitGround.fraction * (feetCollider.distance + slopes.slopeLookAhead))).y;		
											if (maxForce < groundForce)
												maxForce = groundForce;
											isClimbingUpOrDown = false;
											startedClimbing = false;
										}
										
									}
								}
							}
						}
					} else {
						// Calculate slope
						if (slopes.allowSlopes && hitFeet.collider.gameObject.layer != climableLayer) {
							if (lastHitDistance < 0.0f) {
								lastHitDistance = hitFeet.fraction * (feetCollider.distance + slopes.slopeLookAhead);
								lastHitX = feetCollider.offset.x;
								if (slopeCount == -1)
									slopeCount = 0;
							} else {
								slope += Mathf.Atan ((lastHitDistance - hitFeet.fraction * (feetCollider.distance + slopes.slopeLookAhead)) / (feetCollider.offset.x - lastHitX)) * Mathf.Rad2Deg;
								slopeCount++;
								lastHitDistance = hitFeet.fraction * (feetCollider.distance + slopes.slopeLookAhead);
								lastHitX = feetCollider.offset.x;
							}
						}
					}
					
					// If we are hitting our feet on the ground we can't climb down a ladder
					if (hitLadder.collider == null && characterInputY < 0.0f && hitFeet.fraction * (feetCollider.distance + slopes.slopeLookAhead) <= feetCollider.distance) {
						cantClimbDown = true;
						maxForce = 0.0f;
					}
					// Get force to apply		
					if (force > maxForce && hitLadder.collider == null) {
						// We hit a blocker stop all climbing
						cantClimbDown = true;
						isClimbingUpOrDown = false;
						isClimbing = false;
						startedClimbing = false;
						hasHitFeet = true;
						maxForce = force;
						hitGameObject = hitFeet.collider.gameObject;
					}
					
					
				}
			}
			if (startedClimbing && climbCount < climbing.collidersRequired) {
				startedClimbing = false;
			}
			
			if (hasHitFeet) {
				dismounting = null;
				if ((myParent == null || !myParent.overrideY)) {
					if ((myParent is LadderCollider2D && ((LadderCollider2D)myParent).control.ShouldPlayLedgeClimb (this))) {
						if (characterInput.y < 0.0f && myParent is TopStepPlatform2D && climbCount >= climbing.collidersRequired && groundedFeet == 0) {
							isLadderTopClimbing = true; 
							State = CharacterState.CLIMB_TOP_OF_LADDER_DOWN;
							ladderTopClimbState = LadderTopState.CLIMBING_DOWN;
						} else if (characterInput.y > 0.0f && !(myParent is TopStepPlatform2D)) {
							isLadderTopClimbing = true; 
							ladderTopClimbState = LadderTopState.CLIMBING_UP;
							// Force position to be exactly right
							myTransform.position = new Vector3 (myTransform.position.x, ((LadderCollider2D)myParent).LedgeClimbHeight, myTransform.position.z);
						} else {
							myTransform.Translate (0.0f, maxForce, 0.0f, Space.World);	
						}
					} else {
						myTransform.Translate (0.0f, maxForce, 0.0f, Space.World);	
					}
				}
				if (velocity.y < 0.0f) velocity.y = 0.0f;
				if (myParent != null && hitGameObject != myParent.gameObject) { // && !(myParent is Rope)) {
					Unparent ();
				}
				grounded = true;
				fallingTime = 0.0f;
			} else {
				if (myParent == null) {
					ApplyGravity ();
				} else if (!grounded) {
					ApplyGravity ();
					if (!isWallSliding)
						Unparent ();
					startedClimbing = false;
				}	
			}
		} else {
			// If we are mving through a passthrough pltform stop gravity for a little while
			// As long as pass through paltforms are kept thin this works quite well.
			bool holdOffOnGravity = false;
			foreach (RaycastCollider2D foot in feetColliders) {
				if (foot.IsColliding (1 << passThroughLayer)) {
					holdOffOnGravity = true;
				}
			}
			if (!holdOffOnGravity)
				ApplyGravity ();	
		}
		// Force dismount if we dont have enough colliders on the ladder		
		if (climbCount < climbing.collidersRequired && myParent is Ladder2D) {
			Dismount ((Ladder2D)myParent);
		}
		
		// Stop crouch when climbing
		if (isClimbing)
			StopCrouch ();
		
		// Apply rotation from slopes
		if (slopes.allowSlopes) {
			float actualSlope = (myTransform.localEulerAngles.z % 360.0f) + (slope / (float)slopeCount);
			if (slopeCount > 0 && !isClimbing && (!(actualSlope > slopes.maxRotation && actualSlope < 360.0f - slopes.maxRotation))) {
				myTransform.Rotate (0.0f, 0.0f, slopes.rotationSpeed * (slope / (float)slopeCount));
			} else if (slopeCount == -1 || isClimbing) {
				myTransform.localRotation = Quaternion.RotateTowards (myTransform.localRotation, Quaternion.identity, slopes.rotationSpeed * 10.0f);
			}
			if ((actualSlope > slopes.maxRotation && actualSlope < 360.0f - slopes.maxRotation)) {
				myTransform.localRotation = Quaternion.Euler (0, 0, 0);
			}
		}
		
		// Hitting Head
		if (velocity.y > 0.0f || isClimbing || (myParent != null && myParent.velocity.y > 0.0f)) {
			float maxForce = 0.0f;
			foreach (RaycastCollider2D headCollider in headColliders) {
				RaycastHit2D hitHead = headCollider.GetCollision (1 << backgroundLayer);
				float force = (hitHead.normal * (headCollider.distance - (hitHead.fraction * headCollider.distance ))).y;
				if (hitHead.collider != null) {
					// Action on headbut
					Platform2D platform = hitHead.collider.gameObject.GetComponent<Platform2D> ();
					if (platform != null) {
						platform.DoAction (headCollider, this);
					}
					if (force < -1 * movement.skinSize && force < maxForce) {
						hasHitHead = true;
						maxForce = force;
					}
				}
			}
			
			if (hasHitHead) {
				jumpHeldTimer = jump.jumpHeldTime;
				myTransform.Translate (0.0f, maxForce, 0.0f, Space.World);		
				if (velocity.y > 0.0f)
					velocity.y = 0.0f;
			}
			if (!isClimbing) {
				ApplyGravity ();
			} 
		}
		
		// Jump
		if (!hasHitHead || isClimbing) {
			if (characterInput.jumpButtonDown) {
				if ((grounded || myParent != null) && jumpCount == 0 && jumpButtonTimer <= 0.0f) {
					// Special case when launching from a rope
					/* if (myParent != null && myParent is Rope) {
						float k = Mathf.Abs (Mathf.Cos (Mathf.Deg2Rad * myTransform.rotation.eulerAngles.z));
						k = Mathf.Pow (k, ((Rope)myParent).control.jumpFlattenFactor);
						velocity = new Vector2 ((myParent.velocity.x + myParent.velocity.y) * ((Rope)myParent).control.ropeVelocityFactor, 
						                        jump.jumpVelocity * k);
						jumpCount = 2;
					} else
					*/
					if (jump.inheritParentVelocityFactor != 0 && myParent != null) {
						velocity.y = jump.jumpVelocity + (myParent.velocity * jump.inheritParentVelocityFactor).y;
						velocity.x += (myParent.velocity * jump.inheritParentVelocityFactor).x;
						jumpCount = 1;
					} else {
						velocity.y = jump.jumpVelocity * (IsSwimming ? (1 - swimming.waterResistance.y) : 1);
						jumpCount = 1;
					}
					// Inherit parent velocity
					Unparent ();
					startedClimbing = false;
					jumpButtonTimer = jump.jumpTimer;
					jumpHeldTimer = 0.0f;
					StopCrouch ();
					State = CharacterState.JUMPING;
				} else if (jumpCount == 1 && jump.canDoubleJump && !IsSwimming) {
					Unparent ();
					startedClimbing = false;
					jumpCount++;
					velocity.y = jump.doubleJumpVelocity;
					StopCrouch ();
					State = CharacterState.DOUBLE_JUMPING;
				}
			} else if (characterInput.jumpButtonHeld && jumpHeldTimer < jump.jumpHeldTime && jumpCount == 1) {
				velocity.y += jump.jumpFrameVelocity * frameTime * (jump.jumpHeldTime - jumpHeldTimer);
				jumpHeldTimer += frameTime;
			}
		}
		
		// Swimming
		if (IsSwimming){
			if (State != CharacterState.JUMPING && jumpButtonTimer <= 0 && characterInput.swimButtonDown) {
				// Note this also adds acceleration in X!
				velocity.y += swimming.swimStrokeAcceleration.y * frameTime;
				velocity.x += swimming.swimStrokeAcceleration.x * CurrentDirection * frameTime;
				jumpButtonTimer = swimming.swimStrokeTime;
				State = CharacterState.SWIMMING;
			}
		}
		
		if (jumpButtonTimer > 0.0f)
			jumpButtonTimer -= frameTime;
		if (jumpButtonTimer <= 0.0f && grounded) {
			jumpCount = 0;	
		}
		
		// Reset held button timer if we release button
		if (!characterInput.jumpButtonHeld) {
			jumpHeldTimer = jump.jumpHeldTime;
		}
		
		// Wall jump
		if (wallJumpTimer > 0) {
			wallJumpTimer -= frameTime;	
		}
		
		if (wall.canWallJump && (wall.wallJumpTag == "" || wall.wallJumpTag == currentWallTag)) {
			// Easy wall jump
			if (wall.easyWallJump) {
				if (characterInput.jumpButtonDown && isWallHolding) {
					Unparent();
					startedClimbing = false;
					velocity.y = wall.wallJumpSpeed.y;
					jumpCount = 2;
					wallJumpTimer = 0.0f;
					jumpButtonTimer = jump.jumpTimer;
					jumpHeldTimer = 0.0f;
					StopCrouch();
					State = CharacterState.WALL_JUMPING;
					if (wall.wallJumpOnlyInOppositeDirection) {
						oppositeDirectionTimer = wall.oppositeDirectionTime;
						if (wallJumpDirection == RC_Direction.LEFT)  velocity.x = wall.wallJumpSpeed.x;
						else if (wallJumpDirection == RC_Direction.RIGHT)  velocity.x =  -1 * wall.wallJumpSpeed.x;
					}
				}
			}
			// "Hard" wall jump also works for easy wall jump
			if (wallJumpTimer > 0.0f) {
				if ((hasPressedJumpForWallJump && ((wallJumpDirection == RC_Direction.LEFT && characterInput.x > 0) || (wallJumpDirection == RC_Direction.RIGHT && characterInput.x < 0)))
				    
				    || (hasPressedDirectionForWallJump && characterInput.jumpButtonDown)) {
					Unparent();
					startedClimbing = false;
					velocity.y = wall.wallJumpSpeed.y;
					jumpCount = 2;
					wallJumpTimer = 0.0f;
					jumpButtonTimer = jump.jumpTimer;
					jumpHeldTimer = 0.0f;
					StopCrouch();
					State = CharacterState.WALL_JUMPING;
					if (wall.wallJumpOnlyInOppositeDirection) {
						oppositeDirectionTimer = wall.oppositeDirectionTime;
						if (wallJumpDirection == RC_Direction.LEFT)  velocity.x = wall.wallJumpSpeed.x;
						else if (wallJumpDirection == RC_Direction.RIGHT)  velocity.x =  -1 * wall.wallJumpSpeed.x;
					}
				} else if (!hasPressedJumpForWallJump && characterInput.jumpButtonDown ) {
					hasPressedJumpForWallJump = true;
				} else if (!hasPressedDirectionForWallJump && ((wallJumpDirection == RC_Direction.LEFT && characterInput.x > 0) || (wallJumpDirection == RC_Direction.RIGHT && characterInput.x < 0))) {
					hasPressedDirectionForWallJump = true;
				}
			} else {
				hasPressedJumpForWallJump = false;
				hasPressedDirectionForWallJump = false;
			}
		}
		
		if (myParent != null && myParent.overrideAnimation) {
			State = myParent.GetAnimationState(this);
		} else {
			// Animations
			if ((!IsGrounded (groundedLookAhead, false) && !hasHitFeet) || jumpButtonTimer > 0.0f) {
				State = CharacterState.AIRBORNE;
			}
			
			if (velocity.y < jump.fallVelocity) {
				State = CharacterState.FALLING;
			}
			
			if (startedClimbing){
				if (isClimbingUpOrDown) {
					State = CharacterState.CLIMBING;	
				} else {
					State = CharacterState.HOLDING;	
				}
			}
		}
	}
	/// <summary>
	///  Force the character to unparent from the given object.
	/// </summary>
	/// <returns>true if the object was parented to the supplied platform and then successfully unparented.</returns>
	/// <param name="platform">The platform to unparent from.</param>
	public bool Unparent (Platform2D platform) {
		if (myParent == platform) {
			myParent = null;
			myTransform.parent = null;
			return true;
		}
		return false;
	}
	protected void MoveInXDirection (bool grounded)
	{
		// Create a copy of character input which we can modify;
		float characterInputX = characterInput.x;
		
		// Ignore input if stunned
		if (stunTimer > 0.0f)
			characterInputX = 0.0f;
		
		// Ignore input if crouching
		if (isCrouching)
			characterInputX = 0.0f;
		
		// Calculate Velocity
		float actualDrag = 1 - (currentDrag * frameTime);
		
		// Jump Drag
		if (jumpCount > 0 || !grounded) {
			actualDrag = 1 - (jump.drag * frameTime);
		}
		
		// Crouch slide drag		
		if (isCrouchSliding) {
			actualDrag = 1 - (crouchSlideDrag * frameTime);
		}
		if (actualDrag < 0)
			actualDrag = 0;
		
		// Timer which ignores character input while jumping away from a wall
		if (wall.canWallJump && oppositeDirectionTimer > 0.0f) {
			oppositeDirectionTimer -= frameTime;
			if (wallJumpDirection == RC_Direction.RIGHT)
				characterInputX = -0.5f;
			else if (wallJumpDirection == RC_Direction.LEFT)
				characterInputX = 0.5f;
		}
		
		if (characterInputX != 0 && (myParent == null || !myParent.overrideX) && (!grounded || !IsSwimming || swimming.canRun)) {
			bool walking = false;
			if (jumpCount > 0 || !grounded || (characterInputX > 0 && characterInputX < 1.0f) || (characterInputX < 0 && characterInputX > -1.0f))
				walking = true;
			if (movement.movementStyle != MovementStyle.PHYSICS_LIKE && movement.jumpAtRunSpeed && (jumpCount > 0 || !grounded))
				walking = false;
			// TODO Move these behaviours to different functions (can wait till 2.0 upgrade?)
			switch (movement.movementStyle) {
			case MovementStyle.PHYSICS_LIKE:
				float newVelocity = velocity.x + (frameTime * movement.acceleration * characterInputX) * (IsSwimming ? (1 - swimming.waterResistance.x) : 1);
				// Climbing sideways
				if (climbing.allowClimbing && startedClimbing) {
					velocity.x = newVelocity;
					if (velocity.x > climbing.horizontalSpeed)
						velocity.x = climbing.horizontalSpeed;
					if (velocity.x < -1 * climbing.horizontalSpeed)
						velocity.x = -1 * climbing.horizontalSpeed;
				} else if (walking) {
					// If going too fast just apply drag (don't just limit to walk speed else you may get odd jerks)
					if (velocity.x > movement.walkSpeed && characterInputX >= 0.0f || velocity.x < movement.walkSpeed * -1 && characterInputX <= 0.0f) {
						velocity.x = velocity.x * actualDrag;
						// If we went too far go back to walk speed

						if (velocity.x < movement.walkSpeed && characterInputX >= 0.0f) {
							velocity.x = movement.walkSpeed * (IsSwimming ? (1 - swimming.waterResistance.x) : 1);
						} else if (velocity.x > movement.walkSpeed * -1 && characterInputX <= 0.0f) {
							velocity.x = movement.walkSpeed * -1 * (IsSwimming ? (1 - swimming.waterResistance.x) : 1);
						}
					} else {
						velocity.x = newVelocity;
						// Limit to walk speed;
						if (velocity.x > movement.walkSpeed)
							velocity.x = movement.walkSpeed * (IsSwimming ? (1 - swimming.waterResistance.x) : 1);
						if (velocity.x < -1 * movement.walkSpeed)
							velocity.x = -1 * movement.walkSpeed * (IsSwimming ? (1 - swimming.waterResistance.x) : 1);
					}
				} else {
					velocity.x = newVelocity;
					// Limit to run speed;
					if (velocity.x > movement.runSpeed)
						velocity.x = movement.runSpeed * (IsSwimming ? (1 - swimming.waterResistance.x) : 1);
					if (velocity.x < -1 * movement.runSpeed)
						velocity.x = -1 * movement.runSpeed * (IsSwimming ? (1 - swimming.waterResistance.x) : 1);
				}
				break;
			case MovementStyle.DIGITAL:
				if (climbing.allowClimbing && startedClimbing) {
					velocity.x = (characterInput.x > 0 ? 1 : -1) * climbing.horizontalSpeed;
				} else if (walking) {
					velocity.x = (characterInput.x > 0 ? 1 : -1) * movement.walkSpeed * (IsSwimming ? (1 - swimming.waterResistance.x) : 1);
				} else {
					velocity.x = (characterInput.x > 0 ? 1 : -1) * movement.runSpeed * (IsSwimming ? (1 - swimming.waterResistance.x) : 1);
				}
				break;
			case MovementStyle.DIGITAL_WITH_SLIDE:
				if (climbing.allowClimbing && startedClimbing) {
					velocity.x = (characterInput.x > 0 ? 1 : -1) * climbing.horizontalSpeed;
				} else if (walking) {
					velocity.x = (characterInput.x > 0 ? 1 : -1) * movement.walkSpeed * (IsSwimming ? (1 - swimming.waterResistance.x) : 1);
				} else {
					velocity.x = (characterInput.x > 0 ? 1 : -1) * movement.runSpeed * (IsSwimming ? (1 - swimming.waterResistance.x) : 1);
				}
				break;
			}
		} else {
			switch (movement.movementStyle) {
			case MovementStyle.PHYSICS_LIKE:
				velocity.x = velocity.x * actualDrag;
				break;
			case MovementStyle.DIGITAL:
				velocity.x = 0;
				break;
			case MovementStyle.DIGITAL_WITH_SLIDE:
				velocity.x = velocity.x * actualDrag;
				break;
			}
		}
		
		// Apply velocity
		if ((myParent == null || !myParent.overrideX) && velocity.x > movement.skinSize || velocity.x * -1 > movement.skinSize) {
			myTransform.Translate (velocity.x * frameTime, 0.0f, 0.0f);		
		}
		
		float forceSide = 0.0f;
		
		// Ledge Hang variables
		int ledgeHangHitCount = 0;
		Collider2D ledgeHangCollider = null;
		RaycastCollider2D actualLedgeCollider = null;
		
		// Wall slide variables
		int wallSlideCount = 0;
		RaycastCollider2D actualWallCollider = null;
		
		isWallSliding = false;
		isWallHolding = false;
		
		for (int i = 0; i < sides.Length; i++) {
			RaycastHit2D hitsides2D;
			float additionalDistance = 0.0f;
			// If crouching and using autoHeightReduction skip any sides2D higher than provided value
			if (!isCrouching || !crouch.useHeightReduction || sides[i].offset.y <= crouch.ignoredSideCollidersHigherThan) {
				if (ledgeHanging.autoGrab && velocity.y <= 0.0f) additionalDistance = ledgeHanging.autoGrabDistance;
				else if (wall.canWallSlide) additionalDistance = wall.wallSlideAdditionalDistance;
				
				hitsides2D = sides [i].GetCollision (1 << backgroundLayer, additionalDistance);
				
				// Hit something ...
				if (hitsides2D.collider != null) {
					
					// Update ledge hang
					if (ledgeHanging.canLedgeHang && !grounded && velocity.y <= 0.0f) {
						if (sides [i].direction == RC_Direction.RIGHT && (sides [i] == highestSideColliders [1] || sides [i] == highestSideColliders [0])) {
							ledgeHangHitCount++;
							ledgeHangDirection = RC_Direction.RIGHT;
							ledgeHangCollider = hitsides2D.collider;
							if (sides [i] == highestSideColliders [1]) {
								actualLedgeCollider = highestSideColliders [1]; 
							} else {
								actualLedgeCollider = highestSideColliders [0]; 
							}
						} else if (sides [i].direction == RC_Direction.LEFT && (sides [i] == highestSideColliders [1] || sides [i] == highestSideColliders [0])) {
							ledgeHangHitCount++;
							ledgeHangDirection = RC_Direction.LEFT;
							ledgeHangCollider = hitsides2D.collider;
							if (sides [i] == highestSideColliders [1]) {
								actualLedgeCollider = highestSideColliders [1]; 
							} else {
								actualLedgeCollider = highestSideColliders [0]; 
							}
						}
					}
					
					/// Update wall slide
					if ((wall.canWallSlide || wall.canWallJump) && !grounded) {
						if ((sides [i] == highestSideColliders [1] || sides [i] == highestSideColliders [0])) { 
							if (hitsides2D.fraction * (sides[i].distance + additionalDistance) <= sides [i].distance + wall.wallSlideAdditionalDistance) {
								wallSlideCount++;
								wallSlideDirection = sides[i].direction;
								if (sides [i] == highestSideColliders [1]) {
									actualWallCollider = highestSideColliders [1]; 
								} else {
									actualWallCollider = highestSideColliders [0]; 
								}
							}
						}	
					}
					
					// Check for platforms, but only if we are within collider distance + skinSize
					if (hitsides2D.fraction * (sides[i].distance + additionalDistance) <= sides [i].distance + movement.skinSize) {
						Platform2D platform = hitsides2D.collider.gameObject.GetComponent<Platform2D> ();
						if (platform != null) {
							platform.DoAction (sides [i], this);
						}
					}
				}
				
				// Stop movement, but only if we are within collider distance
				if (hitsides2D.fraction * (sides[i].distance + additionalDistance) <= sides [i].distance) {
					float tmpForceSide = (hitsides2D.normal * (sides [i].distance - hitsides2D.fraction * (sides[i].distance + additionalDistance))).x;
					if (tmpForceSide > Mathf.Abs (forceSide) || tmpForceSide * -1 > Mathf.Abs (forceSide)) {
						forceSide = tmpForceSide;
						//	TODO Remove this after adequate testing break;
					}
				}
			}
		}
		
		// Check for ledge hang
		if (ledgeHanging.canLedgeHang && ledgeHangHitCount == 1 && !IsSwimming) {
			bool stopLedgeHang = false;
			if (ledgeHangDirection == RC_Direction.LEFT) {
				if (ledgeHanging.grabOnlyInFacingDirection && CurrentDirection >= 0) {
					stopLedgeHang = true;
				}
				if (actualLedgeCollider.IsColliding (1 << backgroundLayer, ledgeHanging.edgeDetectionOffset.x + ledgeHanging.autoGrabDistance, ledgeHanging.edgeDetectionOffset.y)) {
					stopLedgeHang = true;
				}
				if (!(ledgeHangCollider is BoxCollider2D)) {
					stopLedgeHang = true;
				}
				if (!stopLedgeHang &&
				    ledgeHangCollider.Max().y < myTransform.position.y + actualLedgeCollider.offset.y + ledgeHanging.graspPoint + ledgeHanging.graspLeeway &&
				    ledgeHangCollider.Max().y > myTransform.position.y + actualLedgeCollider.offset.y + ledgeHanging.graspPoint - ledgeHanging.graspLeeway) {
					isLedgeHanging = true;
					jumpCount = 2;
					ledgeHangState = LedgeHangingState.TRANSITION;
					ledgeHangTimer = 0.0f;
					ledgeHangOriginalPosition = myTransform.position;
					ledgeHangGoalPosition = ledgeHanging.hangOffset + new Vector3 (ledgeHangCollider.Max().x, ledgeHangCollider.Max().y, myTransform.position.z);
					// Check for parent
					Platform2D platform = ledgeHangCollider.gameObject.GetComponent<Platform2D> ();
					if (platform != null) {
						Transform parentPlatform = platform.ParentOnStand (this);
						if (parentPlatform != null) {
							myParent = platform;
							if (myTransform.parent != parentPlatform) {
								myTransform.parent = parentPlatform;
							}
							ledgeHangGoalPosition += platform.velocity * ledgeHanging.transitionTime;
						} else {
							// Force ladder to unparent if we have a "bobble"
							if (myParent is Ladder2D) {
								Unparent();
							}
						}
					}
				}
			} else if (ledgeHangDirection == RC_Direction.RIGHT) {
				if (ledgeHanging.grabOnlyInFacingDirection && CurrentDirection <= 0) {
					stopLedgeHang = true;
				}
				if (actualLedgeCollider.IsColliding (1 << backgroundLayer, ledgeHanging.edgeDetectionOffset.x + ledgeHanging.autoGrabDistance, ledgeHanging.edgeDetectionOffset.y)) {
					stopLedgeHang = true;
				}
				if (!(ledgeHangCollider is BoxCollider2D)) {
					stopLedgeHang = true;
				}
				if (!stopLedgeHang &&
				    ledgeHangCollider.Max().y < myTransform.position.y + actualLedgeCollider.offset.y + ledgeHanging.graspPoint + ledgeHanging.graspLeeway &&
				    ledgeHangCollider.Max().y > myTransform.position.y + actualLedgeCollider.offset.y + ledgeHanging.graspPoint - ledgeHanging.graspLeeway) {
					isLedgeHanging = true;
					jumpCount = 2;
					ledgeHangState = LedgeHangingState.TRANSITION;
					ledgeHangTimer = 0.0f;
					ledgeHangOriginalPosition = myTransform.position;
					ledgeHangGoalPosition = ledgeHanging.hangOffset + new Vector3 (ledgeHangCollider.Min().x, ledgeHangCollider.Max().y, myTransform.position.z);
					// Check for parent
					Platform2D platform = ledgeHangCollider.gameObject.GetComponent<Platform2D> ();
					if (platform != null) {
						Transform parentPlatform = platform.ParentOnStand (this);
						if (parentPlatform != null) {
							myParent = platform;
							if (myTransform.parent != parentPlatform) {
								myTransform.parent = parentPlatform;
							}
							ledgeHangGoalPosition += platform.velocity * ledgeHanging.transitionTime;
						}
					}
				}
			}

		}
		
		// Check for wall slide
		if (wallSlideCount > 0 && velocity.y <= 0.0f) {
			isWallHolding = true;
			bool stopWallSlide = true;
			RaycastHit2D hit = actualWallCollider.GetCollision(1<<backgroundLayer, wall.edgeDetectionOffset.x);
			if (hit.collider != null) {
				currentWallTag = hit.collider.gameObject.tag;
			} else {
				currentWallTag = null;
			}
			if (actualWallCollider.IsColliding (1 << backgroundLayer, wall.edgeDetectionOffset.x, wall.edgeDetectionOffset.y)) {
				stopWallSlide = false;
			}
			if (currentWallTag != wall.wallJumpTag) stopWallSlide = true;
			if (!stopWallSlide && wall.canWallSlide && ((wallSlideDirection == RC_Direction.RIGHT && characterInput.x > 0) || (wallSlideDirection == RC_Direction.LEFT && characterInput.x < 0))) {
				// Support sliding on moving platforms
				actualWallCollider.GetCollision(1<< backgroundLayer, 0.1f);
				isWallSliding = true;
				State = CharacterState.WALL_SLIDING;
				// Handle moving platforms
				if (hit.collider != null) {
					Platform2D platform = hit.collider.gameObject.GetComponent<Platform2D>();
					if (platform != null && platform.ParentOnStand(this) != null) {
						myParent = platform;
						myTransform.parent = platform.ParentOnStand(this);
					}
				}
				// End cope with moving platforms
			}
		}
		
		// Move
		if (forceSide > movement.skinSize) {	
			myTransform.Translate(Mathf.Max(velocity.x * frameTime * -1, forceSide), 0.0f, 0.0f);		
			wallJumpDirection = RC_Direction.LEFT;
			wallJumpTimer = wall.wallJumpTime;
			hasPressedJumpForWallJump = false;
			hasPressedDirectionForWallJump = false;
			StopCrouch();
		} else if (-1 * forceSide > movement.skinSize) {		
			myTransform.Translate(Mathf.Min(velocity.x * frameTime * -1, forceSide), 0.0f, 0.0f);	
			wallJumpDirection = RC_Direction.RIGHT;
			wallJumpTimer = wall.wallJumpTime;
			hasPressedJumpForWallJump = false;
			hasPressedDirectionForWallJump = false;
			StopCrouch();
		}
		if ((forceSide > 0 && velocity.x < 0) || (forceSide < 0 && velocity.x > 0)) {
			velocity.x = 0.0f;
		}
		
		// Animation 
		if (grounded) {
			if  (		(velocity.x > movement.walkSpeed && characterInput.x > 0.1f) || 
			     (velocity.x < movement.walkSpeed * -1 && characterInput.x < -0.1f)) {
				State = CharacterState.RUNNING;
			} else if (	(velocity.x > maxSpeedForIdle && characterInput.x > 0.1f) || 
			           (velocity.x < -1 * maxSpeedForIdle  && characterInput.x < -0.1f)){
				State = CharacterState.WALKING;
			} else if (	velocity.x > maxSpeedForIdle || velocity.x < -1 * maxSpeedForIdle ){
				State = CharacterState.SLIDING;
			} else {
				State = CharacterState.IDLE;
			}
		} 
		
		// Reset Drag
		currentDrag = movement.drag;
	}
	/// <summary>
	/// Unparent from platform.
	/// </summary>
	private void Unparent () {
		myParent = null;
		myTransform.parent = null;
	}