My Character teleports instead of smoothly gaining altitude. How do I fix this? (C#)

I’ve got this problem where my Character “Bob”, Jumps into the air like if he was teleporting.
When I press the Jump button he teleports instead of smoothly gaining altitude.
I can’t figure out why it happens and I’m not getting errors either.

Here my entire code attached to “Bob”:

using System.Collections;
  
    [System.Serializable]
    //All values for movement purposes
    public class MovementValues{
        //Movement
        public float Speed;
        [HideInInspector] public Rigidbody2D Rb;
  
        //Jump Values
        [HideInInspector]public bool IsGrounded;
        public Transform GroundCheck;
        public LayerMask WhatShouldBeGround;
  
        public float GroundSphere = 0.3f;
        public float JumpForce, JumpForceHold, MaxJumpTime;
        [HideInInspector]public float MaxJumpTimeInternal;
  
    }
  
    [System.Serializable]
    //Map
    public class MapBoundaryValues{
        public float XMin, YMin, YMax;
        [HideInInspector]public LevelCreator LC;
    }
  
    public class BobHandler : MonoBehaviour {
  
        //Classes
        public MovementValues movementValues;
        public MapBoundaryValues mapBoundaryValues;
  
  
  
        // Use this for initialization
        void Start () {
            movementValues.Rb = GetComponent<Rigidbody2D>();
            mapBoundaryValues.LC = GameObject.Find("LevelMaster").GetComponent<LevelCreator>();
  
        }
  
        void Update(){
  
        }
      
        // Update is called once per frame
        void FixedUpdate () {
            movementValues.IsGrounded = Physics2D.OverlapCircle(movementValues.GroundCheck.position,
                movementValues.GroundSphere,
                movementValues.WhatShouldBeGround
            );
            Movement();
            JumpFunction();
        }
  
        //All movement Logic
        void Movement(){
  
            float HMove = Input.GetAxis("Horizontal");
  
            Vector3 Move = new Vector2(HMove, 0.0f);
            movementValues.Rb.velocity = Move * movementValues.Speed;
  
            movementValues.Rb.position = new Vector3(
                Mathf.Clamp(movementValues.Rb.position.x, mapBoundaryValues.XMin, mapBoundaryValues.LC.GroundSpawnValues.x -0.5f),
                Mathf.Clamp(movementValues.Rb.position.y, mapBoundaryValues.YMin, mapBoundaryValues.YMax),
                0.0f
            );
        }
  
        //Jumping mechanisme
        void JumpFunction(){
  
  
            if(movementValues.IsGrounded && Input.GetButtonDown("Jump")){
                movementValues.Rb.AddForce(new Vector2(0.0f, movementValues.JumpForce));
                movementValues.MaxJumpTimeInternal = movementValues.MaxJumpTime;
            }
  
            if(Input.GetButton("Jump") && movementValues.Rb.velocity.y > 1 && movementValues.MaxJumpTimeInternal > 0){
                movementValues.Rb.AddForce(new Vector2(0.0f, movementValues.JumpForceHold));
                movementValues.MaxJumpTimeInternal = movementValues.MaxJumpTimeInternal - 1;
            }
        }
  
    }

Just guessing here, your code looks okay to me I think. No errors means it’s a logical error, so start commenting out sections until you see a change. Make sure your Clamps are doing what you intended.

Try adding ForceMode2D.Impulse as the second parameter to your AddForce calls. Without that, your forces are persistent and additive every fixed update.

I noticed for jumping you’re using AddForce but for movement you’re setting the velocity directly, why is that?

Also, just a tip – you can use: “movementValues.JumpForce * Vector2.up” to get your force vector, or or “HMove * Vector2.right” for movement vector, so that you’re not creating new Vectors every frame. (pretty negligible optimization but looks nicer to me)

Vector2.up = new Vector(0, 1), and there’s up, down, left, right. Vector3 also has forward and backwards.

1 Like

Thank you!
I went trough the Code Line for line and figured out that my problem had something to do with these lines:

float HMove = Input.GetAxis("Horizontal");
            Vector3 Move = new Vector2(HMove, 0.0f);
            movementValues.Rb.velocity = Move * movementValues.Speed;
            movementValues.Rb.position = new Vector3(
                Mathf.Clamp(movementValues.Rb.position.x, mapBoundaryValues.XMin, mapBoundaryValues.LC.GroundSpawnValues.x -0.5f),
                Mathf.Clamp(movementValues.Rb.position.y, mapBoundaryValues.YMin, mapBoundaryValues.YMax),
                0.0f
            );

I’m not sure why but I will rewrite my logic and try another approach.
Now I can jump tough! :smile:

Again Thank you for the tip and your answer.

Also, I’m not quite sure what this actually does But I will look into it, thanks!

It’s actually just because I began with velocity and it has become a habit.
Do you think addForce will work better for this?

Ohh One last thing:

This peace of code also seems to trouble something:

movementValues.IsGrounded = Physics2D.OverlapCircle(movementValues.GroundCheck.position,
            movementValues.GroundSphere,
            movementValues.WhatShouldBeGround
        );

Everytime this is in the logic it will make the weird jump(Teleport Jumping).
I’ve checked the Scripting API: Physics2D.OverlapCircle and everything seems to be as it should.

public static Collider2D OverlapCircle(Vector2 point, float radius, int layerMask = DefaultRaycastLayers, float minDepth = -Mathf.Infinity, float maxDepth = Mathf.Infinity);

Maybe you got an idea?

Generally speaking it’s best to use AddForce and let the physics system determine the velocity.

If you set the velocity directly, you will overwrite any forces affecting your Rigidbody, and the velocity will be what you set it to. AddForce will elegantly combine all the forces that you add from your input and the resulting velocity will be determined by the physics system.

Check out the docs for ForceMode: Unity - Scripting API: ForceMode2D

I think of Impulse as an explosion or impact force (instant, one time force addition). And I think of Force as a constant force, which will be persistent like a flowing river or wind force.

That IsGrounded check looks good to me, I would check what is using IsGrounded. That check itself wouldn’t cause the player to move, but something else must be using IsGrounded and doing movement.