0
\$\begingroup\$

I recently made the switch to the unity built in character controller, as it better suited the needs of my project. However, after refactoring my code to work with the character controller I've noticed some irregular behaviour with my jump logic. The character seems jump and once they reach the apex they hang in the air for a few frames longer than they should, resulting in a jump that doesnt follow an arc. Here is a gif to show it in action:

Link to gif of issue

Here is how I calculate my gravity value and jump velocity:

 readonly float maxJumpHeight = 10.5f;
 readonly float maxJumpTime = .5f;

timeToPeak = maxJumpTime/2;
gravity = (-2 * maxJumpHeight) / Mathf.Pow(timeToPeak,2);
initialJumpVelocity = 2 * maxJumpHeight/timeToPeak;
currentGravity = gravity;

void HandleJump(){ 
      
        float jumpHeight = 10;
        if(_jumpPressed && (_isGrounded) && !_jumping) {
            velocity.y = initialJumpVelocity;
            _jumping = true;
             currentJumps --;
            _jumpPressed = false;
            _playerSm.jumpDash = false;
            //controller.Move(new Vector3(0,velocity.y,0) * Time.deltaTime);
            
            return;
        }
       
        else if(_jumpPressed && currentJumps > 0 && _jumping && !_isGrounded){
            velocity.y = initialJumpVelocity;
             currentJumps --;
            _jumpPressed = false;
            return;
        }
        else if((!_jumpPressed && _isGrounded && _jumping) || currentJumps <= 0){
        _jumping = false;
        }
    }
    void ApplyGravity(){
        bool isFalling = ((velocity.y <= 0.0f) || !_jumpPressed);
        float fallMultiplier = 1.0f;
        float previousYVelocity = velocity.y;
        float nextYvelocity = 0;
        float newYVelocity;
        if(isFalling){ 
            newYVelocity = velocity.y + currentGravity * fallMultiplier;
            nextYvelocity = (previousYVelocity + newYVelocity) * 0.5f;
            
            
          
        }

        if(!_isGrounded)velocity.y += Mathf.Max(nextYvelocity,-500) * Time.deltaTime; else velocity.y += groundedGravity * Time.deltaTime;
        //if (!_isGrounded) velocity.y += currentGravity * Time.deltaTime;
    }
//This is my classes update method, it gets run every frame
 public void Tick(){
        ApplyGravity();
       
        _move = _controls.GroundMove.Move.ReadValue<Vector2>();
        
        currentYSpeed = Vector3.Distance(new Vector3(0,_prevPos.y,0), new Vector3(0, _playerTransform.position.y, 0))/Time.deltaTime;
        
        GroundCheck();
        // SlopeCheck(); 
        HandleRotation();
        HandleAttack();
       
        
        
      
        if (!lockOnPressed)
        {
            ApplyRotation();
        }
        
        HandleJump();
        
        controller.Move(velocity * Time.deltaTime);
        
        Vector3 currentVelocity =  velocity * ( 1 - Time.deltaTime * dragForce);
        if (!_isGrounded)
        {
            velocity = new Vector3(currentVelocity.x, velocity.y, currentVelocity.z);
        }
        else
        {
            velocity = currentVelocity;
        }
        
       
        
        
        
        //update the animator on our various attributes 
        publisher.updateGroundedStatus(_isGrounded);
        publisher.updateAimStatus(_aiming);
        publisher.updateSpeedStatus(new Vector3(velocity.x,0,velocity.z).magnitude);
        publisher.updateYSpeedStatus(velocity.y);
        publisher.updateForce(velocity);
        publisher.updateVelocity(velocity);
        publisher.updateSubmerged(Physics.CheckSphere(_groundCheck.position, 0.25f , _waterLayer));
    }

 void OnJump(InputAction.CallbackContext context){
    Debug.Log("jump performed " + context.performed);
    if(currentJumps > 0)
    {
       
        _jumpPressed = context.performed;
        _playerTransform.parent = null;
      
        if (_jumpPressed && currentJumps > 0)
        {
            if(_isGrounded)
                publisher.updateJumpedStatus(1);
            else
                publisher.updateJumpedStatus(2);
        }
    }
}

Its odd as sometimes this code produces a perfect arc and sometimes it doesnt, which leads me to believe it might be an issue with my unity project or something else, if anyone could help or insight I would greatly appreciate it!

\$\endgroup\$
4
  • \$\begingroup\$ Do you find the plateaus in the curve are more pronounced when you hold the jump button throughout the arc, and that they disappear when you tap & release the button quickly? That could be due to the fact that you don't apply gravity until the jump button is released, and your drag alone will reduce velocity to zero, but not below zero. \$\endgroup\$
    – DMGregory
    May 7 at 12:52
  • \$\begingroup\$ I dont have variable jump height in the game, so regardless of how long the jump button is pressed the plataeu still remains a constant, even if i just tap the jump button while not moving, the character still hangs in the air at the apex for a little too long. \$\endgroup\$
    – Jambo
    May 7 at 13:35
  • \$\begingroup\$ You may want to show us where _jumpPressed gets set to true then. We can see where it gets set to false, but not the other side, nor where Tick() gets called, etc. Aim to have a self-contained example in your question, where a reader could paste the code into a new, empty project and have it compile and reproduce the problem. \$\endgroup\$
    – DMGregory
    May 7 at 14:00
  • \$\begingroup\$ I've udpated my response to show where _jumpPressed is set to true and to clarify the functions, I'm using a state machine so Tick() is my Update() \$\endgroup\$
    – Jambo
    May 7 at 14:13

1 Answer 1

1
\$\begingroup\$

So, I did some more testing, it seems like when I locked the frame rate it seemed to solve the issue. Initially, the game ran at 300-400 fps with an unlocked frame rate, whereas using Application.targetFrameRate = 60; seems to have solved the issue. I'm guessing the really low value for Time.deltaTime may have been introducing irregularities.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .