protected override void ComputeVelocityBeforeMovement() { // When going in opposite direction from previous movement, transit to it. if (isGoingOppositeSide || ((lastMovement != 0) && !Mathm.HaveDifferentSign(lastMovement - movement.x, lastMovement))) { isGoingOppositeSide = true; // About-Turn. if ((movement.x != 0) && Mathm.HaveDifferentSign(lastMovement, movement.x)) { float _coef = isGrounded ? attributes.GroundAboutTurnAccel : attributes.AirAboutTurnAccel; movement.x = Mathf.MoveTowards(lastMovement, movement.x, speed * Time.deltaTime * _coef); } // Deceleration. else if (lastMovement != movement.x) { float _coef = isGrounded ? attributes.GroundMovementDecel : attributes.AirMovementDecel; movement.x = Mathf.MoveTowards(lastMovement, movement.x, Time.deltaTime * _coef); } else { isGoingOppositeSide = false; } } lastMovement = movement.x; base.ComputeVelocityBeforeMovement(); }
/// <summary> /// Move rigidbody according to a complex collision system. /// When hitting something, continue movement all along hit surface. /// Perform movement according to ground surface angle. /// </summary> private void ComplexCollisionsSystem() { // If grounded, adjust velocity according to ground normal. Vector2 _velocity = GetVelocity(); if (isGrounded) { Vector2 _x = Vector2.Perpendicular(groundNormal); if (_x.x < 0) { _x *= -1; } _x *= _velocity.x; Vector2 _y = (_velocity.y < 0 ? groundNormal : Vector2.up) * _velocity.y; _velocity = _x + _y; } castBufferCount = 0; RecursiveComplexCollisions(_velocity, groundNormal); // Modify force according to hit surfaces. if (!force.IsNull()) { for (int _i = 0; _i < castBufferCount; _i++) { if (Mathm.HaveDifferentSignAndNotNull(force.x, castBuffer[_i].normal.x) && (Mathf.Abs(castBuffer[_i].normal.x) == 1)) { force.x = 0; if (force.y == 0) { break; } } if ((force.y < 0) && (castBuffer[_i].normal.y > ProgramSettings.I.GroundMinYNormal)) { force.y = 0; if (force.x == 0) { break; } } } } // Reset instant force and movement. instantForce = movement = Vector2.zero; }
/// <summary> /// Rotates this vector of a certain angle. /// </summary> /// <param name="_vector">Vector to rotate.</param> /// <param name="_angle">Angle to rotate vector by.</param> /// <returns>Returns new rotated vector.</returns> public static Vector2 Rotate(this Vector2 _vector, float _angle) => Mathm.RotateVector(_vector, _angle);
/// <summary> /// Get if a Vector2 is null, that is /// if its x & y values are equal to zero. /// </summary> /// <param name="_vector">Vector to check.</param> /// <returns>Returns true if both x & y Vector2 values /// are equal to zero, false otherwise.</returns> public static bool IsNull(this Vector2 _vector) => Mathm.IsVectorNull(_vector);
protected virtual void ComputeVelocityBeforeMovement() { // Slowly decrease force over time. if (force.x != 0) { float _maxDelta = isGrounded ? ProgramSettings.I.GroundDecelerationForce : ProgramSettings.I.AirDecelerationForce; // Calculs when going to opposite force direction. if (movement.x != 0) { if (Mathm.HaveDifferentSign(force.x, movement.x)) { _maxDelta = Mathf.Max(_maxDelta, Mathf.Abs(movement.x) * 2); movement.x = Mathf.MoveTowards(movement.x, 0, Mathf.Abs(force.x) * Time.deltaTime); } else { movement.x = Mathf.Max(0, Mathf.Abs(movement.x) - Mathf.Abs(force.x)) * Mathf.Sign(movement.x); } } // Calculs when going to opposite force direction, // compared to previous frame. float _previousXOtherVelocity = previousXVelocity - previousXForce; if (Mathm.HaveDifferentSignAndNotNull(_previousXOtherVelocity, previousXForce)) { float _difference = Mathf.Abs(_previousXOtherVelocity); if (!Mathm.HaveDifferentSign(_previousXOtherVelocity, instantForce.x + movement.x)) { _difference -= Mathf.Abs(instantForce.x + movement.x); } if (_difference > 0) { force.x = Mathf.MoveTowards(force.x, 0, _difference); } } // Reduce force if (_maxDelta != 0) { force.x = Mathf.MoveTowards(force.x, 0, _maxDelta * Time.deltaTime); } } // ----------------------- previousXForce = force.x; previousXVelocity = force.x + instantForce.x + movement.x; // If going to opposite force direction, accordingly reduce force and movement. if (Mathm.HaveDifferentSignAndNotNull(force.y, movement.y)) { float _maxDelta = Mathf.Abs(movement.y); movement.y = Mathf.MoveTowards(movement.y, 0, Mathf.Abs(force.y)); force.y = Mathf.MoveTowards(force.y, 0, _maxDelta * Time.deltaTime); } }