void movement() { // Gathering information : int contactCount = motor.getContactCount(); Vector2 leftTangent = Vector2.zero; Vector2 rightTangent = Vector2.zero; Vector2 leftNormal = Vector2.zero; Vector2 rightNormal = Vector2.zero; Vector2 oldSpeed = speed; float oldSpeedNorm = Vector2.Distance(speed, Vector2.zero); if (contactCount >= 1) { leftTangent = motor.getLeftTangent().normalized; rightTangent = motor.getRightTangent().normalized; leftNormal = motor.getLeftNormal().normalized; rightNormal = motor.getRightNormal().normalized; } bool isLeftMovement = Vector2.Angle(speed, leftTangent) < Vector2.Angle(speed, rightTangent); bool leftGround = Vector2.Angle(Vector2.up, leftNormal) < groundAngle; bool rightGround = Vector2.Angle(Vector2.up, rightNormal) < groundAngle; bool leftWall = Vector2.Angle(Vector2.up, leftNormal) < 91 && !leftGround; bool rightWall = Vector2.Angle(Vector2.up, rightNormal) < 91 && !rightGround; bool leftCeiling = !leftGround && !leftWall; bool rightCeiling = !rightGround && !rightWall; // Movement choices : bool ld = Input.GetKey(KeyCode.Q) && !Input.GetKey(KeyCode.D); bool rd = Input.GetKey(KeyCode.D) && !Input.GetKey(KeyCode.Q); bool ud = Input.GetKey(KeyCode.Z) && !Input.GetKey(KeyCode.S); bool bd = Input.GetKey(KeyCode.S) && !Input.GetKey(KeyCode.Z); bool stick = Input.GetKey(KeyCode.LeftShift); bool jump = Input.GetKeyDown(KeyCode.Space); // walk order : bool goRight = (Vector2.Angle(Vector2.up, rightNormal) < 80 && rd); goRight |= (Vector2.Angle(-Vector2.up, rightNormal) < 80 && ld); goRight |= (Vector2.Angle(Vector2.right, rightNormal) < 80 && bd); goRight |= (Vector2.Angle(-Vector2.right, rightNormal) < 80 && ud); bool goLeft = (Vector2.Angle(Vector2.up, leftNormal) < 80 && ld); goLeft |= (Vector2.Angle(-Vector2.up, leftNormal) < 80 && rd); goLeft |= (Vector2.Angle(Vector2.right, leftNormal) < 80 && ud); goLeft |= (Vector2.Angle(-Vector2.right, leftNormal) < 80 && bd); // nudge order : bool nudgeLeft = ld && !rd; bool nudgeRight = rd && !ld; // walk condition : bool acceptRightWalk = contactCount >= 1 && rightGround; acceptRightWalk |= contactCount == 1 && rightWall && stick && (Vector2.Dot(rightTangent, Vector2.up) < 0 || !isLeftMovement) && oldSpeedNorm > 0.1f; acceptRightWalk |= contactCount >= 1 && rightCeiling && stick && oldSpeedNorm > 0.1f; bool acceptLeftWalk = contactCount >= 1 && leftGround; acceptLeftWalk |= contactCount >= 1 && leftWall && stick && (Vector2.Dot(leftTangent, Vector2.up) < 0 || isLeftMovement) && oldSpeedNorm > 0.1f; acceptLeftWalk |= contactCount >= 1 && leftCeiling && stick && oldSpeedNorm > 0.1f; // nudge condition : bool acceptLeftNudge = contactCount == 0; acceptLeftNudge |= contactCount == 1 && !stick && leftWall && !leftGround && !rightGround && Vector2.Dot(leftNormal, -Vector2.right) > 0; acceptLeftNudge |= contactCount == 2 && !stick && leftWall && !leftGround && !rightGround && Vector2.Dot(leftNormal, -Vector2.right) > 0 && Vector2.Dot(rightNormal, -Vector2.right) > 0; bool acceptRightNudge = contactCount == 0; acceptRightNudge |= contactCount == 1 && !stick && leftWall && !leftGround && !rightGround && Vector2.Dot(leftNormal, Vector2.right) > 0; acceptRightNudge |= contactCount == 2 && !stick && leftWall && !leftGround && !rightGround && Vector2.Dot(leftNormal, Vector2.right) > 0 && Vector2.Dot(rightNormal, Vector2.right) > 0; bool acceptIdling = contactCount >= 1 && (leftGround || rightGround) && !goLeft && !goRight; // gravity bool applyGrav = contactCount == 0; bool applyWallGrav = contactCount >= 1 && (leftWall || leftCeiling) && !leftGround; // idle if (acceptIdling) { //Debug.Log ("idling"); Vector2 delta = Vector2.zero; if (isLeftMovement) { //Debug.Log ("idling right"); delta = idleAcceleration * rightTangent * Time.deltaTime; } else { //Debug.Log("idling left"); delta = idleAcceleration * leftTangent * Time.deltaTime; } if (Vector2.Dot(delta + speed, oldSpeed) <= 0) { speed = Vector2.zero; } else { speed += delta; } } if (applyGrav) { //Debug.Log ("gravity"); speed += gravity * Time.deltaTime; } if (applyWallGrav) { //Debug.Log ("wall gravity"); if (Vector2.Dot(leftTangent, -Vector2.up) > 0) { speed += Vector2.Dot(gravity * wallGravMultiplier, leftTangent) * leftTangent * Time.deltaTime; } else if (Vector2.Dot(rightTangent, -Vector2.up) > 0) { speed += Vector2.Dot(gravity * wallGravMultiplier, rightTangent) * rightTangent * Time.deltaTime; } } if (applyWallGrav && !(goLeft && acceptLeftWalk) && !(goRight && acceptRightWalk)) { //Debug.Log ("wall drag"); speed += -wallDrag * speed * Time.deltaTime; } // nudge if (nudgeLeft && acceptLeftNudge) { //Debug.Log ("nudge left"); speed += -(nudge * Time.deltaTime) * Vector2.right; } if (nudgeRight && acceptRightNudge) { //Debug.Log ("nudge right"); speed += (nudge * Time.deltaTime) * Vector2.right; } // walk right if (goRight && acceptRightWalk) { //Debug.Log ("go right"); if (isLeftMovement) { Vector2 delta = switchAcceleration * rightTangent * Time.deltaTime; if (Vector2.Dot(oldSpeed + delta, speed) < 0) { speed -= Vector2.Dot(speed, rightTangent) * rightTangent; } else { speed += delta; } } else if (oldSpeedNorm < maxWalkSpeed) { speed += walkAcceleration * rightTangent * Time.deltaTime; } } // walk left if (goLeft && acceptLeftWalk) { //Debug.Log ("go left"); if (!isLeftMovement) { Vector2 delta = switchAcceleration * leftTangent * Time.deltaTime; if (Vector2.Dot(oldSpeed + delta, speed) < 0) { speed -= Vector2.Dot(speed, leftTangent) * leftTangent; } else if (oldSpeedNorm < maxWalkSpeed) { speed += delta; } } else if (oldSpeedNorm < maxWalkSpeed) { speed += walkAcceleration * leftTangent.normalized * Time.deltaTime; } } // jump if (contactCount >= 1) { jumping = false; } if (jumping && Input.GetKeyUp(KeyCode.Space) && Time.time - lastJump < maxJumpStop && speed.y > jumpSpeed / 2) { speed -= Vector2.up * jumpSpeed / 2; jumping = false; } if (jump) { if (contactCount >= 1) { if (leftGround || rightGround) { lastJump = Time.time; jumping = true; speed += jumpSpeed * Vector2.up; } else if (leftWall && !(goRight && acceptRightWalk || goLeft && acceptLeftWalk)) { // Debug.Log ("wall drag jump"); if (Vector2.Dot(leftNormal, Vector2.right) > 0) { speed = jumpSpeed * (Vector2.up * 2 + Vector2.right).normalized; } else { speed = jumpSpeed * (Vector2.up * 2 - Vector2.right).normalized; } } else { speed += jumpSpeed * (Vector2.Angle(leftNormal, Vector2.up) < Vector2.Angle(rightNormal, Vector2.up) ? leftNormal : rightNormal); } } } // rocket influence if (Input.GetMouseButton(0) && fuel > 0) { Vector2 direction = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position; float distance = Vector2.Distance(Camera.main.ScreenToWorldPoint(Input.mousePosition), transform.position); float strength = minRocketForce[rocketLevel] + (maxRocketForce[rocketLevel] - minRocketForce[rocketLevel]) * distance / rocketRadius; float force = Mathf.Min(strength, maxRocketForce[rocketLevel]) * Time.deltaTime; force = Mathf.Min(fuel / fuelPerForce, force); float projectedSpeed = Vector2.Dot(oldSpeed, direction.normalized); if (projectedSpeed < terminalRocketSpeed) { speed += direction.normalized * force; } fuel -= force * fuelPerForce; } // stepping movement if (nudgeLeft && acceptLeftNudge && (leftWall || leftCeiling)) { motor.move(-0.1f * Time.deltaTime * Vector2.right); } if (nudgeRight && acceptRightNudge && (leftWall || leftCeiling)) { motor.move(0.1f * Time.deltaTime * Vector2.right); } if (leftCeiling && (!stick || (isLeftMovement && goRight) || (!isLeftMovement && goLeft) || oldSpeedNorm < ceilingDropOffSpeed)) { motor.move(-0.1f * Time.deltaTime * Vector2.up); } Vector2 movement = speed * Time.deltaTime; movement = adaptSpeedToContact(movement); int a = 0; while (Vector2.Distance(movement, Vector2.zero) > 0.001f && a < 10) { a++; movement = motor.move(movement); movement = adaptSpeedToContact(movement); } }
void Update() { isGrounded = (motor.getContactCount() >= 1 && Vector2.Angle(Vector2.up, motor.getLeftNormal()) < 88) || (motor.getContactCount() >= 2 && Vector2.Angle(Vector2.up, motor.getRightNormal()) < 88); speed += gravity * Time.deltaTime; if (isGrounded) { if (Input.GetKey(KeyCode.Q) && Vector2.Angle(Vector2.up, motor.getLeftNormal()) < 88) { speed = walkSpeed * motor.getLeftTangent(); } else if (Input.GetKey(KeyCode.D) && Vector2.Angle(Vector2.up, motor.getRightNormal()) < 88) { speed = walkSpeed * motor.getRightTangent(); } else { speed = Vector2.zero; } if (Input.GetKeyDown(KeyCode.Space)) { speed.y += jumpSpeed; } } else { if (Input.GetKey(KeyCode.Q)) { speed += -nudge * Time.deltaTime * Vector2.right; } if (Input.GetKey(KeyCode.D)) { speed += nudge * Time.deltaTime * Vector2.right; } } if (motor.getContactCount() >= 1) { Vector2 normal = motor.getLeftNormal(); if (Vector2.Dot(normal, speed) < 0) { speed -= Vector2.Dot(speed, normal) * normal; } } if (motor.getContactCount() == 2) { Vector2 normal = motor.getRightNormal(); if (Vector2.Dot(normal, speed) < 0) { speed -= Vector2.Dot(speed, normal) * normal; } } Vector2 movement = speed * Time.deltaTime; while (Vector2.Distance(movement, Vector2.zero) > 0.001f) { movement = motor.move(movement); if (motor.getContactCount() >= 1) { speed -= Vector2.Dot(speed, motor.getLeftNormal()) * motor.getLeftNormal(); } } /*if (Input.GetKeyDown (KeyCode.Q)) { * motor.move(-Vector2.right/3); * } * if (Input.GetKeyDown (KeyCode.D)) { * motor.move (-Vector2.left/3); * } * if (Input.GetKeyDown (KeyCode.Z)) { * motor.move(Vector2.up/3); * } * if (Input.GetKeyDown (KeyCode.S)) { * motor.move (-Vector2.up / 3); * }*/ }
void movement() { // Gathering information : int contactCount = motor.getContactCount(); Vector2 leftTangent = Vector2.zero; Vector2 rightTangent = Vector2.zero; Vector2 leftNormal = Vector2.zero; Vector2 rightNormal = Vector2.zero; Vector2 oldSpeed = speed; float oldSpeedNorm = 0; switch (direction) { case Direction.free: oldSpeedNorm = Vector2.Distance(speed, Vector2.zero); break; case Direction.left: oldSpeedNorm = leftSpeed; break; case Direction.right: oldSpeedNorm = rightSpeed; break; } if (contactCount >= 1) { leftTangent = motor.getLeftTangent().normalized; rightTangent = motor.getRightTangent().normalized; leftNormal = motor.getLeftNormal().normalized; rightNormal = motor.getRightNormal().normalized; } bool isLeftMovement = direction == Direction.left; bool leftGround = Vector2.Angle(Vector2.up, leftNormal) < groundAngle; bool rightGround = Vector2.Angle(Vector2.up, rightNormal) < groundAngle; bool leftWall = Vector2.Angle(Vector2.up, leftNormal) < 91 && !leftGround; bool rightWall = Vector2.Angle(Vector2.up, rightNormal) < 91 && !rightGround; bool leftCeiling = !leftGround && !leftWall; bool rightCeiling = !rightGround && !rightWall; // Movement choices : bool ld = Input.GetKey(KeyCode.Q) && !Input.GetKey(KeyCode.D); bool rd = Input.GetKey(KeyCode.D) && !Input.GetKey(KeyCode.Q); bool ud = Input.GetKey(KeyCode.Z) && !Input.GetKey(KeyCode.S); bool bd = Input.GetKey(KeyCode.S) && !Input.GetKey(KeyCode.Z); bool stick = Input.GetKey(KeyCode.LeftShift); bool jump = Input.GetKeyDown(KeyCode.Space); // walk order : bool goRight = (Vector2.Angle(Vector2.up, rightNormal) < 80 && rd); goRight |= (Vector2.Angle(-Vector2.up, rightNormal) < 80 && ld); goRight |= (Vector2.Angle(Vector2.right, rightNormal) < 80 && bd); goRight |= (Vector2.Angle(-Vector2.right, rightNormal) < 80 && ud); bool goLeft = (Vector2.Angle(Vector2.up, leftNormal) < 80 && ld); goLeft |= (Vector2.Angle(-Vector2.up, leftNormal) < 80 && rd); goLeft |= (Vector2.Angle(Vector2.right, leftNormal) < 80 && ud); goLeft |= (Vector2.Angle(-Vector2.right, leftNormal) < 80 && bd); // nudge order : bool nudgeLeft = ld && !rd; bool nudgeRight = rd && !ld; // walk condition : bool acceptRightWalk = contactCount >= 1 && rightGround; acceptRightWalk |= contactCount == 1 && rightWall && stick && (Vector2.Dot(rightTangent, Vector2.up) < 0 || !isLeftMovement); acceptRightWalk |= contactCount >= 1 && rightCeiling && stick && oldSpeedNorm > 0.1f; bool acceptLeftWalk = contactCount >= 1 && leftGround; acceptLeftWalk |= contactCount >= 1 && leftWall && stick && (Vector2.Dot(leftTangent, Vector2.up) < 0 || isLeftMovement); acceptLeftWalk |= contactCount >= 1 && leftCeiling && stick && oldSpeedNorm > 0.1f; // nudge condition : bool acceptLeftNudge = contactCount == 0; acceptLeftNudge |= contactCount == 1 && !stick && (leftWall || leftCeiling) && !leftGround && !rightGround && Vector2.Dot(leftNormal, -Vector2.right) > 0; acceptLeftNudge |= contactCount == 2 && !stick && (leftWall || leftCeiling) && !leftGround && !rightGround && Vector2.Dot(leftNormal, -Vector2.right) > 0 && Vector2.Dot(rightNormal, -Vector2.right) > 0; bool acceptRightNudge = contactCount == 0; acceptRightNudge |= contactCount == 1 && !stick && (leftWall || leftCeiling) && !leftGround && !rightGround && Vector2.Dot(leftNormal, Vector2.right) > 0; acceptRightNudge |= contactCount == 2 && !stick && (leftWall || leftCeiling) && !leftGround && !rightGround && Vector2.Dot(leftNormal, Vector2.right) > 0 && Vector2.Dot(rightNormal, Vector2.right) > 0; bool acceptIdling = contactCount >= 1 && (leftGround || rightGround) && !goLeft && !goRight; // gravity bool applyGrav = contactCount == 0; bool applyWallGrav = contactCount >= 1 && (leftWall || leftCeiling) && !leftGround && !rightGround; bool applyDrag = !(acceptRightWalk && goRight) && !(acceptLeftWalk && goLeft) && leftWall; // jump if (leftGround && Time.time - lastJump > maxJumpStop) { jumping = false; } if (jumping && Input.GetKeyUp(KeyCode.Space) && Time.time - lastJump < maxJumpStop) { if (direction == Direction.free && speed.y > 0) { speed.y /= (1 + speed.y / jumpSpeed); } else if (direction == Direction.left && Vector2.Dot(Vector2.up, leftTangent) > 0) { leftSpeed /= (1 + leftSpeed / jumpSpeed); } else if (direction == Direction.right && Vector2.Dot(Vector2.up, rightTangent) > 0) { rightSpeed /= (1 + rightSpeed / jumpSpeed); } jumping = false; } // leap jump if (leapFrame >= leapMaxFrame || contactCount >= 1) { leaped = false; } if (leaped) { if (leapFrame < leapMaxFrame && jump) { speed += jumpSpeed * Vector2.up; jumping = true; lastJump = Time.time; direction = Direction.free; } leapFrame++; } if (contactCount == 0) { direction = Direction.free; speed += gravity * Time.deltaTime; if (ld) { speed += -nudge * Vector2.right * Time.deltaTime; } if (rd) { speed += nudge * Vector2.right * Time.deltaTime; } } else { if (jump) { if (leftGround || rightGround) { speed = jumpSpeed * Vector2.up; jumping = true; lastJump = Time.time; } else if (leftWall || leftCeiling) { if (applyDrag) { if (Vector2.Dot(leftNormal, Vector2.right) > 0) { speed = jumpSpeed * (Vector2.right + Vector2.up * 2.5f).normalized; } else { speed = jumpSpeed * (-Vector2.right + Vector2.up * 2.5f).normalized; } jumping = true; lastJump = Time.time; } else { speed = jumpSpeed * leftNormal; } } if (!applyDrag) { switch (direction) { case Direction.free: break; case Direction.left: speed += leftTangent * leftSpeed; break; case Direction.right: speed += rightTangent * rightSpeed; break; } } direction = Direction.free; } else if (Vector2.Angle(leftNormal, -Vector2.up) < 80 && (acceptRightWalk && goRight && isLeftMovement || acceptLeftWalk && goLeft && !isLeftMovement || oldSpeedNorm < ceilingDropOffSpeed || !stick)) { speed = -Vector2.up * 0.5f; switch (direction) { case Direction.free: break; case Direction.left: speed += leftTangent * leftSpeed; break; case Direction.right: speed += rightTangent * rightSpeed; break; } direction = Direction.free; } else { if (acceptLeftNudge && ld) { speed = -(nudge * Time.deltaTime + 0.5f) * Vector2.right; switch (direction) { case Direction.free: break; case Direction.left: speed += leftTangent * leftSpeed; break; case Direction.right: speed += rightTangent * rightSpeed; break; } direction = Direction.free; } else if (acceptRightNudge && rd) { speed = (nudge * Time.deltaTime + 0.5f) * Vector2.right; switch (direction) { case Direction.free: break; case Direction.left: speed += leftTangent * leftSpeed; break; case Direction.right: speed += rightTangent * rightSpeed; break; } direction = Direction.free; } else { if (acceptRightWalk && goRight) { if (direction == Direction.left) { if (leftSpeed > 0.01f) { float delta = switchAcceleration * Time.deltaTime; if (leftSpeed - delta > 0) { leftSpeed -= delta; } else { leftSpeed = 0; rightSpeed = 0; direction = Direction.right; } } else { direction = Direction.right; rightSpeed = walkAcceleration * Time.deltaTime; } } else if (rightSpeed < maxWalkSpeed) { direction = Direction.right; rightSpeed += walkAcceleration * Time.deltaTime; } } else if (acceptLeftWalk && goLeft) { if (direction == Direction.right) { if (rightSpeed > 0.01f) { float delta = switchAcceleration * Time.deltaTime; if (rightSpeed - delta > 0) { rightSpeed -= delta; } else { rightSpeed = 0; leftSpeed = 0; direction = Direction.left; } } else { direction = Direction.left; leftSpeed = walkAcceleration * Time.deltaTime; } } else if (leftSpeed < maxWalkSpeed) { direction = Direction.left; leftSpeed += walkAcceleration * Time.deltaTime; } } else if (acceptIdling) { if (direction == Direction.right) { float delta = idleAcceleration * Time.deltaTime; if (rightSpeed - delta > 0) { rightSpeed -= delta; } else { rightSpeed = 0; } } else { float delta = idleAcceleration * Time.deltaTime; if (leftSpeed - delta > 0) { leftSpeed -= delta; } else { leftSpeed = 0; } } } if (applyWallGrav) { if (direction == Direction.right) { if (Vector2.Dot(Vector2.up, rightTangent) > 0) { rightSpeed += Vector2.Dot(gravity, rightTangent) * wallGravMultiplier * Time.deltaTime; if (rightSpeed < 0) { leftSpeed = -rightSpeed; direction = Direction.left; } } else { rightSpeed += Vector2.Dot(gravity, rightTangent) * wallGravMultiplier * Time.deltaTime; } } else { if (Vector2.Dot(Vector2.up, leftTangent) > 0) { leftSpeed += Vector2.Dot(gravity, leftTangent) * wallGravMultiplier * Time.deltaTime; if (leftSpeed < 0) { rightSpeed = -leftSpeed; direction = Direction.right; } } else { leftSpeed += Vector2.Dot(gravity, leftTangent) * wallGravMultiplier * Time.deltaTime; } } } if (applyDrag) { if (direction == Direction.right) { if (Vector2.Dot(-Vector2.up, rightTangent) > 0) { rightSpeed -= wallDrag * oldSpeedNorm * Time.deltaTime; if (rightSpeed < 0) { rightSpeed = 0; } } } else { if (Vector2.Dot(-Vector2.up, leftTangent) > 0) { leftSpeed -= wallDrag * oldSpeedNorm * Time.deltaTime; if (leftSpeed < 0) { leftSpeed = 0; } } } } } } } if (Input.GetMouseButton(0) && fuel > 0) { Vector2 rocketDirection = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position; float distance = Vector2.Distance(Camera.main.ScreenToWorldPoint(Input.mousePosition), transform.position); float strength = minRocketForce[rocketLevel] + (maxRocketForce[rocketLevel] - minRocketForce[rocketLevel]) * distance / rocketRadius; float force = Mathf.Min(strength, maxRocketForce[rocketLevel]) * Time.deltaTime; force = Mathf.Min(fuel / fuelPerForce, force); float projectedSpeed = Vector2.Dot(oldSpeed, rocketDirection.normalized); if (projectedSpeed < terminalRocketSpeed) { switch (direction) { case Direction.free: speed += rocketDirection.normalized * force; break; case Direction.right: if (Vector2.Dot(rightTangent, rocketDirection) > 0 && Vector2.Dot(rightNormal, rocketDirection) < 0.1f) { rightSpeed += force; } else if (Vector2.Dot(leftTangent, rocketDirection) > 0 && Vector2.Dot(leftNormal, rocketDirection) < 0.1f) { rightSpeed -= force; if (rightSpeed < 0) { leftSpeed = -rightSpeed; direction = Direction.left; } } else { speed = rightSpeed * rightTangent + rocketDirection.normalized * force; direction = Direction.free; } break; case Direction.left: if (Vector2.Dot(rightTangent, rocketDirection) > 0 && Vector2.Dot(rightNormal, rocketDirection) < 0.1f) { leftSpeed -= force; if (leftSpeed < 0) { rightSpeed = -leftSpeed; direction = Direction.right; } } else if (Vector2.Dot(leftTangent, rocketDirection) > 0 && Vector2.Dot(leftNormal, rocketDirection) < 0.1f) { leftSpeed += force; } else { speed = leftSpeed * leftTangent + rocketDirection.normalized * force; direction = Direction.free; } break; } speed += rocketDirection.normalized * force; } fuel -= force * fuelPerForce; } if (direction == Direction.free && contactCount >= 1) { if (Vector2.Dot(speed, leftNormal) <= 0.005f && Vector2.Dot(speed, leftTangent) > 0) { direction = Direction.left; leftSpeed = Vector2.Dot(speed, leftTangent); } else if (Vector2.Dot(speed, rightNormal) <= 0.005f && Vector2.Dot(speed, rightTangent) > 0) { direction = Direction.right; rightSpeed = Vector2.Dot(speed, rightTangent); } } Vector2 freeMovement = speed * Time.deltaTime; float leftMovement = leftSpeed * Time.deltaTime; float rightMovement = rightSpeed * Time.deltaTime; Vector2 tmp = Vector2.zero; int a = 0; while (((contactCount == 0 && Vector2.Distance(speed, Vector2.zero) > 0.001f) || (contactCount >= 1 && ((direction == Direction.left && leftMovement > 0.001f) || (direction == Direction.right && rightMovement > 0.001f) || (direction == Direction.free && Vector2.Distance(speed, Vector2.zero) > 0.001f)))) && a < 10) { Vector2 oldLeftTangent = leftTangent; Vector2 oldRightTangent = rightTangent; Vector2 oldLeftNormal = leftNormal; Vector2 oldRightNormal = rightNormal; rightGround = contactCount >= 1 && Vector2.Angle(rightNormal, Vector2.up) < groundAngle; leftGround = contactCount >= 1 && Vector2.Angle(leftNormal, Vector2.up) < groundAngle; if (contactCount == 0) { tmp = motor.move(freeMovement); } if (contactCount >= 1) { if (direction == Direction.left) { if (motor.isLeftContactEdge()) { tmp = motor.move(leftMovement * leftTangent); } else { if (contactCount < 2 || leftMovement > 0.001f) { // when there are 2 contact, we want to avoid moving very little from that corner tmp = motor.leftLineMove(leftMovement); } } } else if (direction == Direction.right) { if (motor.isRightContactEdge()) { tmp = motor.move(rightMovement * rightTangent); } else { if (contactCount < 2 || rightMovement > 0.001f) { tmp = motor.rightLineMove(rightMovement); } } } else { tmp = motor.move(freeMovement); } } contactCount = motor.getContactCount(); if (contactCount == 0) { switch (direction) { case Direction.free: break; case Direction.left: speed = leftSpeed * leftTangent; if (Vector2.Angle(Vector2.up, leftNormal) < groundAngle) { leaped = true; leapFrame = 0; leapNormal = leftNormal; } break; case Direction.right: speed = rightSpeed * rightTangent; if (Vector2.Angle(Vector2.up, leftNormal) < groundAngle) { leaped = true; leapFrame = 0; leapNormal = rightNormal; } break; } freeMovement = Vector2.zero; direction = Direction.free; } else { leftTangent = motor.getLeftTangent(); rightTangent = motor.getRightTangent(); leftNormal = motor.getLeftNormal(); rightNormal = motor.getRightNormal(); if (tmp != Vector2.zero) { if (Vector2.Angle(tmp, motor.getLeftTangent()) < Vector2.Angle(tmp, motor.getRightTangent())) { if (contactCount < 2 || (Vector2.Angle(leftTangent, rightTangent) > 110 && (stick || Vector2.Angle(leftNormal, Vector2.up) < groundAngle || !rightGround)) || Vector2.Angle(leftNormal, Vector2.up) < groundAngle) { switch (direction) { case Direction.free: leftSpeed = Vector2.Dot(speed, leftTangent); break; case Direction.left: leftSpeed = Vector2.Dot(oldLeftTangent, leftTangent) * leftSpeed; break; case Direction.right: leftSpeed = Vector2.Dot(rightSpeed * oldRightTangent, leftTangent); break; } leftMovement = Vector2.Dot(motor.getLeftTangent(), tmp); direction = Direction.left; } else { leftSpeed = 0; leftMovement = 0; direction = Direction.left; } } else { if (contactCount < 2 || (Vector2.Angle(leftTangent, rightTangent) > 110 && (stick || Vector2.Angle(rightNormal, Vector2.up) < groundAngle || !leftGround)) || Vector2.Angle(rightNormal, Vector2.up) < groundAngle) { switch (direction) { case Direction.free: rightSpeed = Vector2.Dot(speed, rightTangent); break; case Direction.left: rightSpeed = Vector2.Dot(leftSpeed * oldLeftTangent, leftTangent) * rightSpeed; break; case Direction.right: rightSpeed = Vector2.Dot(oldRightTangent, rightTangent) * rightSpeed; break; } rightMovement = Vector2.Dot(motor.getRightTangent(), tmp); direction = Direction.right; } else { rightSpeed = 0; rightMovement = 0; direction = Direction.right; } } } else { switch (direction) { case Direction.free: if (Vector2.Angle(speed, motor.getLeftTangent()) < Vector2.Angle(speed, motor.getRightTangent())) { direction = Direction.left; leftSpeed = Vector2.Dot(speed, motor.getLeftTangent()); } else { direction = Direction.right; rightSpeed = Vector2.Dot(speed, motor.getRightTangent()); } break; case Direction.left: leftMovement = 0; break; case Direction.right: rightMovement = 0; break; } } } a++; } }