bool GetStepInfo(out StepFound step, ContactPoint contact, ContactPoint ground, bool isGrounded) { step = null; RaycastHit stepTest; Vector3 stepOverbite = Vector3.ProjectOnPlane(-contact.normal.normalized, transform.up).normalized * stepOverbiteMagnitude; // Start the raycast position directly above the contact point with the step Debug.DrawRay(contact.point, transform.up * (maxStepHeight * 0.8f), Color.blue, 10); Vector3 raycastStartPos = contact.point + transform.up * (maxStepHeight * 0.8f); // Move the raycast inwards towards the stair (we will be raycasting down at the stair) Debug.DrawRay(raycastStartPos, stepOverbite, Color.red, 10); raycastStartPos += stepOverbite; Vector3 direction = -transform.up; Debug.DrawRay(raycastStartPos, direction * maxStepHeight, Color.green, 10); bool stepFound = contact.otherCollider.Raycast( new Ray(raycastStartPos, direction), out stepTest, maxStepHeight ); if (stepFound) { bool stepIsGround = Vector3.Dot(stepTest.normal, transform.up) > isGroundThreshold; if (!stepIsGround) { return(false); } Vector3 groundPointOrBottomOfPlayer = isGrounded ? ground.point : bottomOfPlayer; float stepHeight = Vector3.Dot(transform.up, stepTest.point - groundPointOrBottomOfPlayer); Vector3 stepOffset = stepOverbite + transform.up * (stepHeight + 0.02f); Debug.DrawRay(contact.point, stepOffset, Color.black, 10); step = new StepFound(contact, stepOffset); debug.Log($"Step: {contact}\n{stepOffset:F3}\nstepHeight:{stepHeight}"); } return(stepFound); }
void FixedUpdate() { UpdateGroundedState(); if (stopped || grounded.standingOnHeldObject) { allContactThisFrame.Clear(); return; } UpdateJumping(); Vector3 desiredVelocity = thisRigidbody.velocity; if (grounded.isGrounded) { desiredVelocity = CalculateGroundMovement(grounded.contact); } else { desiredVelocity = CalculateAirMovement(); } // Prevent player from floating around on cubes they're holding... if (grounded.standingOnHeldObject) { desiredVelocity += 4 * Physics.gravity * Time.fixedDeltaTime; } float movingBackward = Vector2.Dot( new Vector2(desiredVelocity.x, desiredVelocity.z), new Vector2(transform.forward.x, transform.forward.z) ); if (movingBackward < -0.5f) { float slowdownAmount = Mathf.InverseLerp(-.5f, -1, movingBackward); desiredVelocity.x *= Mathf.Lerp(1, backwardsSpeed, slowdownAmount); desiredVelocity.z *= Mathf.Lerp(1, backwardsSpeed, slowdownAmount); } if (!input.LeftStickHeld && !input.SpaceHeld && grounded.ground != null && grounded.ground.CompareTag("Staircase")) { thisRigidbody.constraints = RigidbodyConstraints.FreezeAll; } else { thisRigidbody.constraints = RigidbodyConstraints.FreezeRotation; } StepFound stepFound = DetectStep(desiredVelocity, grounded.contact, grounded.isGrounded); if (stepFound != null) { transform.Translate(stepFound.stepOffset, Space.World); Player.instance.cameraFollow.SetLerpSpeed(CameraFollow.desiredLerpSpeed); if (Vector3.Dot(transform.up, stepFound.stepOffset) > 0) { OnStaircaseStepUp?.Invoke(); } } thisRigidbody.useGravity = !grounded.isGrounded; thisRigidbody.velocity = desiredVelocity; // Apply wind resistance Vector3 projectedVertVelocity = ProjectedVerticalVelocity(); if (!grounded.isGrounded && Vector3.Dot(Physics.gravity.normalized, projectedVertVelocity.normalized) > 0) { thisRigidbody.AddForce( transform.up * projectedVertVelocity.magnitude * thisRigidbody.mass * windResistanceMultiplier ); } allContactThisFrame.Clear(); }