I have a character that’s jumping and pushing a wall constantly. In some games you kind of slow down when this happens, but I don´t want that and that’s precisely what is happening. Am doing a projection of the movement on the wall to calculate the new direction after colliding, then setting that (or the equivalent velocity) to the velocity. Here is a simplified version of my code for clarity:
void Update()
{
float horizontal = Input.GetAxisRaw("Horizontal") * moveSpeed;
velocity.x = horizontal;
if (Input.GetButtonDown("Jump") && canJump)
{
velocity.y += initialVelocity; //jump impulse
isGrounded = false;
canJump = false;
}
if (!isGrounded)
{
velocity.y -= gravity * Time.deltaTime;
}
movement = velocity * Time.deltaTime;//movement is displacement
movement += projectionMovement;
projectionMovement = Vector3.zero;
if (movement != Vector3.zero)
{
Collisions();
}
}
void Collisions() //we want it to collide and move the next frame
{
preventCrash++;
if (!isGrounded)
{
if (movement != Vector3.zero)
{
MoveCollide_AndProject();
if (movement.magnitude < 0.003f && projectionMovement != Vector3.zero) //if, for example, tries to jump when is pushing a wall and collides immediately
{
movement = projectionMovement;
projectionMovement = Vector3.zero;
MoveCollide_AndProject();
}
}
}
}
void MoveCollide_AndProject ()
{
float closestT = GetClosestT(); //this returns a value that ranges from 0-1, which basically is how close a colision occured.
if (closestT < 1) //if player collided
{
Vector3 _movement = movement;
float original_moveMagnitude = movement.magnitude;
Vector3 movement_magOne = movement / original_moveMagnitude;
movement = movement_magOne * hitDistance;
float acc_omittedMagnitude = original_moveMagnitude - acc_hitDistance;
this.transform.Translate(movement, Space.World); //basically moves until collision. If it´s confusing just ignore it, is not that relevant for the problem;
Vector3 originalMotionEnd = acc_hitPoint + (movement_magOne * acc_omittedMagnitude);
bool is3D = false;
Vector3 _realHitNormal = realHitNormal;
if (!is3D) _realHitNormal.z = 0;
float onCollisionPlane = Vector3.Dot(realHitNormal, acc_hitPoint);
float point = Vector3.Dot(realHitNormal, originalMotionEnd);
float point_d = Vector3.Dot(realHitNormal, _realHitNormal);
float d = (onCollisionPlane - point) / point_d;
Vector3 endOfProjection = originalMotionEnd + _realHitNormal * d;
projectionMovement = endOfProjection - acc_hitPoint;
print("velocity before projection: " + velocity.x + ", " + velocity.y + ", " + velocity.z);
Vector3 hitTo_OriginalEnd = originalMotionEnd - acc_hitPoint;
hitTo_OriginalEnd /= Time.deltaTime;
velocity -= hitTo_OriginalEnd; //subtract omitted motion and add the other one (divided by deltaTime because we want the velocity, not the displacement)
velocity += (projectionMovement / Time.deltaTime);
print("velocity after_ projection: " + velocity.x + ", " + velocity.y + ", " + velocity.z);
}
else
{
print("velocity with no collision: " + velocity.x + ", " + velocity.y + ", " + velocity.z);
this.transform.Translate(movement, Space.World);
}
}
The print shows that the velocity was the same before and after the collision (which is right). However, when is pushing the wall is clearly taking longer to ascend or descend. Apparently, the velocity is fine, and takes the same amount of frames for both types of jumps (pushing or not pushing the wall). It is necessary to explain that the framerate is dropping a lot for the method that am using for collisions (I’ll fix it later), which makes me believe is a simple matter of a delta time. I mean, is dropping more when is pushing the wall and that might affect the calculations. However, even if fixing the framerate solves the problem (which I don´t know) I think that we should fix it from its roots and make it framerate independent.
Thanks in advance.
Edit: I have confirmed that the problem is gone if I fix the framerate. Is there a way of doing this? I thought of placing it in fixedUpdate(), but because getting player Input there can lead to bugs, is there another way?