protected override void FixedUpdate() { base.FixedUpdate(); // Apply the Fun Inverse Gravity if (invertGravity) { rb.AddForce(-2 * Physics.gravity, ForceMode.Acceleration); } if (Player.CanControlPlayer) { // Convert user input to movement vector Vector3 movement = new Vector3(Keybinds.Horizontal(), 0f, Keybinds.Vertical()); // If is unclamped and upside-down, keep movement in an intuitive direction for the player // Rotate movement to be in direction of camera and clamp magnitude if (SettingsMenu.settingsData.cameraClamping == 0 && CameraController.UpsideDown) { movement.x = -movement.x; movement = CameraController.CameraDirection * Vector3.ClampMagnitude(movement, 1); movement = -movement; } else { movement = CameraController.CameraDirection * Vector3.ClampMagnitude(movement, 1); } if (IsGrounded) { // if a Jump is queued if (jumpQueued) { jumpQueued = false; Rigidbody targetRb = groundedChecker.StandingOnCollider.attachedRigidbody; Vector3 jumpForce; // Apply Pewter Jump, if sprinting if (IsSprinting) { Drain(gramsPewterPerJump, timePewterPerJump); particleSystem.transform.rotation = particleDirection; particleSystem.transform.position = Player.PlayerInstance.transform.position + particleSystemPosition; if (movement.sqrMagnitude <= .01f) // Vertical jump { movement = Vector3.up; // groundedChecker.Normal; // If movement is going INTO the wall, we must be jumping up it } else if (Vector3.Dot(groundedChecker.Normal, movement) < -0.01f) { float angle = Vector3.Angle(movement, groundedChecker.Normal) - 90; movement = Quaternion.AngleAxis(angle, Vector3.Cross(Vector3.up, groundedChecker.Normal)) * movement; if (movement.y < 0) { movement.y = -movement.y; } } jumpForce = Vector3.ClampMagnitude(groundedChecker.Normal * jumpHeight + movement * jumpDirectionModifier, jumpPewterMagnitude); particleDirection = Quaternion.LookRotation(-jumpForce); particleSystem.transform.rotation = particleDirection; particleSystem.Play(); } else { jumpForce = groundedChecker.Normal * jumpHeight; } rb.AddForce(jumpForce, ForceMode.Impulse); // Apply force and torque to target if (targetRb) { Vector3 radius = groundedChecker.Point - targetRb.worldCenterOfMass; targetRb.AddForce(-jumpForce, ForceMode.Impulse); targetRb.AddTorque(Vector3.Cross(radius, -jumpForce)); } } // If moving or pushing or pulling, apply weaker drag if (movement.sqrMagnitude > 0 || Player.PlayerIronSteel.IronPulling || Player.PlayerIronSteel.SteelPushing) { // You: "why use ints to represent binary values that should be represented by booleans" // Me, an intellectual: rb.drag = SettingsMenu.settingsData.playerAirResistance * dragAirborneLinear; } else { // If not moving and not pushing or pulling, apply stronger drag and pull player to a stop rb.drag = SettingsMenu.settingsData.playerAirResistance * dragGroundedLinear; rb.angularDrag = dragGroundedAngular; } } else // If airborne, reduce movement magnitude { rb.drag = SettingsMenu.settingsData.playerAirResistance * dragAirborneLinear; rb.angularDrag = dragAirborneAngular; //movement *= airControlFactor; } if (movement.sqrMagnitude > 0) // If moving at all // Apply Pewter Sprint, if possible { if (IsSprinting) { // if sprinting // Play particles if just sprinting on the ground for the first time if (!lastWasSprintingOnGround && IsGrounded) { particleDirection = Quaternion.LookRotation(-movement); particleSystem.transform.rotation = particleDirection; particleSystem.Play(); } //movement *= pewterAcceleration * Mathf.Max(maxSprintingSpeed - Vector3.Project(rb.velocity, movement.normalized).magnitude, 0); rb.maxAngularVelocity = maxSprintingAngularVelocity; lastWasSprintingOnGround = IsGrounded; // only show particles after hitting the ground physicsMaterial.dynamicFriction = frictionDynamicSprinting; rb.inertiaTensor = new Vector3(momentOfInertiaMagnitudeSprinting, momentOfInertiaMagnitudeSprinting, momentOfInertiaMagnitudeSprinting); } else { // not Sprinting, move normally. //movement = MovementMagnitude(movement); rb.maxAngularVelocity = maxRollingAngularSpeed; lastWasSprintingOnGround = false; // If Walking, reduce movment if (Keybinds.Walk()) { movement *= movementFactor; rb.inertiaTensor = new Vector3(momentOfInertiaMagnitudeWalking, momentOfInertiaMagnitudeWalking, momentOfInertiaMagnitudeWalking); physicsMaterial.dynamicFriction = frictionDynamicWalking; } else { rb.inertiaTensor = new Vector3(momentOfInertiaMagnitude, momentOfInertiaMagnitude, momentOfInertiaMagnitude); physicsMaterial.dynamicFriction = frictionDynamicRolling; } } // Convert movement to torque //Vector3 torque = Vector3.Cross(IsGrounded ? groundedChecker.Normal : Vector3.up, movement) * torqueFactor; Vector3 torque = Vector3.Cross(Vector3.up, movement); Vector3 feedback = rb.angularVelocity; Vector3 target = torque * maxRollingSpeed; if (IsSprinting) { target *= pewterSpeedFactor; } torque = pidSpeed.Step(feedback, target); //Debug.Log("speed : " + rb.velocity.magnitude); //float dot = Vector3.Dot(torque, rb.angularVelocity); //if(dot < 0) { // torque *= 2 - Mathf.Exp(dot / dotFactor); //} // Apply torque to player rb.AddTorque(torque, ForceMode.Acceleration); // Apply a small amount of the movement force to player for tighter controls & air movement rb.AddForce((CameraController.UpsideDown ? -movement : movement) * airControlFactor * rollingAcceleration, ForceMode.Acceleration); // Debug Debug.DrawRay(transform.position, rb.angularVelocity, Color.red); Debug.DrawRay(transform.position, torque, Color.white); Debug.DrawRay(transform.position, movement, Color.blue); } } else { rb.drag = SettingsMenu.settingsData.playerAirResistance * dragNoControl; } }