Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Rigidbody2D - mysterious force shooting player upwards

Discussion in 'Physics' started by Nyriell, Jun 3, 2020.

  1. Nyriell

    Nyriell

    Joined:
    May 22, 2018
    Posts:
    11
    2 years ago I did a game for a skill test. Now I'm working on another game in another unity version. What they have in common is that both are 2D sideview games, with the character moving left-right and jumping. The jumping in the old game was made with addForce, in the new one it's made by modifying the rigBody.velocity. It works fine in both cases. However, when jumping near a tall wall or jumping on tall steps (so the collider is touching both the ground and the wall before jumping, at least I think so), sometimes a mysterious force shoots the player extremely high up in the air. Gravity will bring him back down eventually. Other times if there is a ceiling, he gets stuck in the corner between the wall and the ceiling until I move him away from the wall. In the newer game, it also happened when the player was struck by an enemy arrow which pushed him a little bit backwards and again, if there is a wall behind, sometimes he will be thrown in the air. It makes me insane because it happens only sometimes (rarely actually, and I can't stress this enough). When it happened, I checked the code multiple times, debugged and the velocity.y gets changed at a constant rate of +1 between updates but not by my code so I'm guessing it has something to do with Unity and rigidbodies. Also, under the rigbody contacts I found a contact with the wall with normal impulse 0.9 (don't remember the rest of the decimals) so I assumed the wall was pushing the player upwards. But that's just a guess.
    It's annoying because at the end of the day I have no idea if I fixed it or if it's just not happening as it is a rare thing.
    Any idea what causes this and how to remove this "feature"?
     
  2. Djedjeska

    Djedjeska

    Joined:
    Dec 24, 2016
    Posts:
    6
    I'm not sure if it is related, but I noticed that in 3D, there is always this bug of being able to climb a vertical wall by frenetically pushing the jumb button. I remember that could be solved by using a physics material (with zero friction for instance)
    check this thread, maybe there will be some answers inside :
    https://forum.unity.com/threads/2d-game-movement-issues-stuck-on-walls.182046/
     
  3. Nyriell

    Nyriell

    Joined:
    May 22, 2018
    Posts:
    11
    The player already has a material with zero friction and bounciness. Now I added it to the wall as well but jumping near a wall sent me in the air again. I'm not sure how a sweep test could help me. I think I should find the origin of this mysterious upward force so I could try to counter it or avoid it. While I was stuck up there in the corner, I just tapped the arrow key in the opposite direction of the wall and the character fell back down.
    And thank you for trying to help :)
     
  4. Nyriell

    Nyriell

    Joined:
    May 22, 2018
    Posts:
    11
    Update:
    I still cannot understand how to avoid this mysterious force. I tried "cancelling" it by doing something like:

    Code (CSharp):
    1. if (!jumping && rigBody.velocity.y > 0)
    2.         rigBody.velocity = new Vector2(rigBody.velocity.x, -10);
    Now, instead of being thrown up to the ceiling, the player starts "jumping"/flickering... Like going a bit up but my new code makes him go down again. But then my code stops changing the velocity so the player starts going up again, which triggers that if and brings him down again and so he jumps up and down.
    Any ideas on how to avoid that force in the first place?
     
  5. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,105
    I've never seen this and you saying that the velocity is changing by +1 is even more suspicious because there's a limit of allowed velocity changes due to contacts which is way below that kind of change.

    Maybe you've got crazy high mass ratios i.e. one body with small mass vs another with high mass. Joints can cause velocity "explosions". Also constraining position but allow velocity to build up but it not being used then not constraining allows the velocity to be applied to position. This is all guesswork.

    2D physics uses Box2D which is extremely stable. Unity doesn't change the simulation at all, it's all stock Box2D. Are you sure you're not using high gravity and/or gravity scale? Have you modified the 2D physics settings? Again, more guesswork.
     
  6. Nyriell

    Nyriell

    Joined:
    May 22, 2018
    Posts:
    11
    The player is on automass, the environment doesn't have a mass option in my inspector (maybe because it's static?). I'm not using the joint components. I inherited the project from another programmer who left the team, so I'm not sure if he changed the physics settings. However, the player's gravity scale is 0 and gravity is applied through code (not sure why it was done like this):
    rigBody.velocity -= new Vector2(0, MovementData.GravityEqualizator * MovementData.Gravity * Time.deltaTime);

    What you wrote about constraints got me curious. While the player is idle, a script puts a constraint on his position.x. When he stops being idle (either to jump or when he's hit), that constraint is removed. But it only freezes the x position, never the y.
    Just in case, I'm uploading the screenshots of:
    Player's rigidbody
    PlayerRigidbody.PNG

    Ground's rigidbody:
    GroundRigidbody.PNG

    Physics settings:
    Physics2D settings.PNG

    I just find it so weird that it happened to me both when I was a complete noob 2 years ago, and now again whereas no one else seems to have encountered it! Maybe I should make a new empty project, draw an environment and place a new player programmed only for running and jumping just to see if it'll happen again? Problem is, I've been trying to recreate this bug for the entire day in my current project and it's just not happening! Recreating it is a nightmare. Since it's so rare, I'm thinking about leaving it. But it still bothers me and I fear it'll happen to players once it gets published...
     
  7. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,105
    Hopefully you're not doing this per-frame. You're using Time.deltaTime which Unity implicity returns Time.fixedDeltaTime when called via the fixed-update so wanted to check that.

    There's too many unknowns here TBH. Maybe show your movement code. If you're manually manipulating velocity then maybe you're getting some nan somewhere that gives you a crazy impulse. No idea.
     
  8. Nyriell

    Nyriell

    Joined:
    May 22, 2018
    Posts:
    11
    The gravity code was in Update, I tried moving it to FixedUpdate since I keep reading that physics stuff goes there. Anyway, I got the upward push in both cases.
    Each of these states is a separate class but all the velocity changes happen in FixedUpdates. The MovementData (speed, gravity, jumpHeight) are all loaded from a file when the game is run.
    Running:
    Code (CSharp):
    1. MovementData.HorizontalMovement = (Input.GetKey(keybinds.KeyboardRight) ? 1 : 0) + (Input.GetKey(keybinds.KeyboardLeft) ? -1 : 0);
    2. rigBody.velocity = new Vector2(MovementData.HorizontalMovement * MovementData.MovementSpeed, rigBody.velocity.y);
    Jumping:
    rigBody.velocity = new Vector2(rigBody.velocity.x, MovementData.Gravity * MovementData.JumpHeightMultiplicator);

    Taking dmg:
    rigBody.velocity = new Vector2(direction * force, rigBody.velocity.y);

    Direction is by default 0, otherwise it gets set to 1 or -1. Force is by default 1, unless the dmg dealer changes is.

    Each of these is a state and while it's active, the velocity is set in FixedUpdate. When exiting or entering some of the states, the velocity.x will be set to 0 if necessary.
    I placed breakpoints on the lines that modify velocity.y but they weren't hit while debugging so I supposed it isn't a coding problem.
    Because of the whole state-machine implementation and the number of classes attached to an object, I don't think it's practical to show entire classes. I will try to isolate it in a smaller project and see if it persists