godot icon indicating copy to clipboard operation
godot copied to clipboard

CharacterBody3D jitters against static bodies, gets worse the bigger the collision shapes are and the farther away from the world origin/CharacterBody3D they are.

Open viksl opened this issue 2 years ago • 13 comments
trafficstars

Godot version

4.0.0, 4.0.1 (c#)

System information

Windows 10, Nvidia GTX 1660Ti, Vulkan

Issue description

I have a game with larger colliders for walls and the ground. Character body just breaks on it. Colliding with walls causes it to jitter. Moving on the ground causes the body to randomly stop (body gets stuck).

I'm not sure if there's a way to get over this or not an whether this is intended or a bug so please let me know I'd greatly appreciate it, I'm just dumb at this point.

I've tested the project on both 4.0.0 and 4.0.1, same issues.

I've tried changing shape's margin, physics frames up, steps and the other thing to give more interations and/or time for the physics to solve this better but nothing helped so far.

This issues happens even with smaller more regular sized colliders but the jitter is small so it's not very noticeable although I can certainly see.

Movement is done through the CharacterBody3D generated code, only adjustment I did was that I removed the jump lines since they were not necessary for the minimal project.

Thank you very much for help!

Video link (turn the sound on) from the minimal reproduction project showcasing my issues: https://youtu.be/Dz-0q6kFz7U.

Minimal reproduction project is in gdscript not c#.

Steps to reproduce

I've put together minimal reproduction project and a video with just base colliders and movement, not representing my game case exactly but the jitter is more than apparent.

  1. Open the project.
  2. Hold up arrow until you hit the wall, keep holding up.
  3. Start sliding along the wall to sides by holding up and left or up and right arrows.
  4. Observe the jitter.
  5. Move the wall up (Y axis) until the bottom side is just below the ground to move it farther away from the world origin.
  6. Repeat 2-4 (jitter should be a lot more apparent)
  7. Change collision shapes of the CharacterBody3D to sphere, cylinder and repeat previous steps.

Minimal reproduction project

TestLargeColliders.zip

viksl avatar Mar 31 '23 17:03 viksl

  • Related to https://github.com/godotengine/godot/issues/36729.

Use a WorldMarginShape resource instead of a very large BoxShape for infinitely large floors/walls/ceilings. If you need a very large but not infinitely large box collider, split it into several smaller shapes.

Calinou avatar Mar 31 '23 20:03 Calinou

I tried it just now but it results in the same behaviour as in the video (movement jitter).

I am considering cutting the colliders into smaller shapes but as I mentioned above the jitter also occurs with small collision shapes, although less noticeable.

Honestly I'm just really not sure how to approach this :0.

EDIT: @Calinou Ok it seems that the size of colliders might not be that much of a matter. For now I just gave it a quick test so I'll know more later today but in my main project I replaced a gigantic godot collider with a gigantic custom collider from blender which has more faces and so far so good - just early tests so far. I guess it's more about how war the vertices are per colliding face rather than the size of the entire shape then?

Oki, I've replaced the large shape by even larger one but more complex as mentioned above and it seems to work so I don't think the overall size is much of an issue itself, I'd still consider this more of a workaround since the godot generated shapes don't work this way. I'm not sure where this comes from, does the distance between vertices matter for the collision resolution?

viksl avatar Mar 31 '23 21:03 viksl

@Calinou

Sorry to bother you but would you mind checking this: https://youtu.be/UcHz3L4Hw2Y it's a 3 minute video I made (turn the sound on). I changed colliders to smaller sizes and you can see in the video that the CharacterBody3D apart from jittering actually gets stuck inside the collider. Please check the entire video since it's not well visible on the recording, particularly you can see at around 2:06 the jitter and then it's stuck and later in the video again (this time with floating mode).

The speed isn't particularly high either.

Also as mentioned above I tried smaller colliders with the grounded mode but jitter is still there.

I don't think this is just a Documentation issues as labeled but is there please some I could discuss this with, I'm really not sure who to tag?

Thank you very much.

PS: I put this into separate comment because I had issues with the edit in the comment above, for some reason my edits were not properly saving. I'm not sure if this is an issue on my side with the browser or some connection issues so I'll try in a day or so to join the two comments to avoid polluting polute this thread.

viksl avatar Apr 02 '23 18:04 viksl

@viksl I tried your project in Godot compiled with double precision (64 bit) floats and there was no jitter. So likely the problem is caused by limited precision of single-precision 32-bit floats when getting far from the origin.

Is it possible for you to use Godot compiled with double precision floats for you project (scons option precision=double)?

GNSS-Stylist avatar Apr 02 '23 21:04 GNSS-Stylist

@GNSS-Stylist I think that would be possible but, I did not mention it in the last post since I didn't want to create an extra replay with github edit not working for me properly today, although in the video I had all the movement 2km (2000m) away I also tested it around the the world origin on a 50mx50m collider which is a small size and the issues were also present.

I'll be definitely checking the double precision built at some point too, I just need to figure out how to put it together (in my case a c# version) which might take me a while. But in general that's why I dropped the new reply since it confuses me why it happens even so close to the origin. If needed I can drop a vid with it?

EDIT: @GNSS-Stylist Ok, so here's a video showcasing this to the best of my poor ability, this time it's 9 minutes sorry for that but I wanted to show and say what is in the scene and how. I moved everything to be around the world origin, very reasonable sizes for colliders, I even tried a different colider to showcase the issues.

What happens is:

  1. Jittery movement (jumping up and down, if you were to zoom in closer you would actually find the body is constantly in up and down movement when colliding but I mostly care about the visible jitter at reasonable distance - although for fps game the smaller jitter I assume can make a world of a difference too).
  2. Colliders aftter couple seconds get stuck in each other - I just asume this, but for some reason the body stops being able to move, godot does not freeze, output is still going, movement vector is ok too, transform.basis is ok too as all showcased in the video.
  3. In the video I showed this with a floating mode but similar things happen with the grounded mode which I opened this issue with.
  4. It seems to happen with all collider shapes (godot ones as well as custom ones imported from blender and build with trimesh as convex/concave shapes - I can't remember which one the trimesh generates :-D).
  5. In the video I'm not moving the object other than with a gravity downwards but the body gets stuck after a while of moving it around too.

Link to the video (turn on sound): https://youtu.be/SDCVQn4ZVwc

Feel free to tell me I'm stupid doing something wrong, at this point I'm just running in circles and can't figure it out, I'd really appreciate help. Lastly, unfortunately I don't think double precision is the solution to this issue because as you can see I'm just around the world origin, colliders have very reasonable sizes, this either shouldn't be happening or I'm doing something wrong I've been missing and again would greatly appreciate advice.

What do you please think?

Thank you very much!

PS: I tried this in 4.0.0 as well as 4.0.2 RC1 (both c# versions but with gdscript code as is in the MRP) and 4.0.0 standard (not c# build).

EDIT2: It seems I'm not the only one noticing this: https://www.youtube.com/watch?v=ZLTYlZgZc-0

viksl avatar Apr 02 '23 21:04 viksl

@viksl I'm not an expert on this matter, but just noticed that your original problem looked like the problems I had earlier. For example in this project: https://github.com/GNSS-Stylist/3D_Scan_Road physics get quite jittery (for example objects dropped to the ground keep jumping) when getting far from the origin of the collision shape (ground) and using single-precision floats. Actually in this case it doesn't seem to matter how far from the world origin you are as physics work just fine with a smaller collision shape (in this case a van). If you like to play with this, use "konami code" to activate spawning of physics objects to the roof of the van (later you can just press "k" to spawn). Other keys are shown on the help panel.

But this project was made in Godot 3.x (just tried it on the latest 3.5.2 stable and it seemed to work) and bullet physics, so it may not be very relevant in this case (although precision issues might be quite similar in both cases).

GNSS-Stylist avatar Apr 04 '23 08:04 GNSS-Stylist

@GNSS-Stylist Oki, let's ignore my last post and the one before, sorry I accidentaly commented only the first line of the code and did not notice it until now.

Anyway my original report still stands that's a different issues and for some reason even with the grounded mode my character can stop sliding under certain circumstances but I'll work on my game for now and see eventually what's going on. I for now agree this might be worth being documented.

But if you guys don't mind I still have a question: In this link here you can see that the body jitters (all colliders small, location aroundworld origin) when I move forward straight while if I move to side then it does not do this. What could be a cause for this? There's nothing in code this time and it's weird. Since it's movement around 0 is it some imprecision or +0 vs -0 or something? Since this is on a small scale down the double precision shouldn't be an issue I assume? Link: https://youtu.be/9c2sHx0tHAs

Thanks!

viksl avatar Apr 04 '23 13:04 viksl

With a new different project I'm confident to say that it's move_and_slide which is broken, this is related to this issues at least partially: https://github.com/godotengine/godot/issues/72988 , my own video is here, this issues is very consistent, in the video I was trying various inputs and angles but if I test it as usual I have 100% rate of reproduction, here's my short video https://youtu.be/LYeZ5yU0ca4 it's collisions in general not just rigid, same issues with character x character, character x rigid, character x static. When I lock the Y aix in CharacterBody3D the character still gets stuck and can't move but doesn't jitter, happens also in mid of collision shape nto jsut on corner but it's not as prevalent and mostly depends on angle you approach the wall.

In the floating motion mode the CharacterBody3D for me gets completely stuck on corners and does not get unstuck at all, edges and corners are just dangerous in general even on a single collision shape, regular sizes, around origin and so on. :-)

Interestingly as mentioned in the other thread changing Wall Min Slide Angle/Max Angle does influence this, you can go from getting stuck to moving at a snail speed which obviously doesn't help much either.

I wish I could help better but the move_and_slide code is too complicated for my pea size brain.

EDIT: This also happens on straight walls when you have for example multiple bodies next to each other, this can be particularly disturbing when you have a line like this and the bodies are just slightly off meaning not a perfectly straight wall but the dent is tiny, this can cause the CharacterBody3D to get stuck at seemigly nothing or barely anything considering the differences between the colliders's sizes.

EDIT (27.4.2023): Ok here in this video: https://youtu.be/DZOaIdlXN5o I checked what happens to Velocity and RealVelocity (GetRealVelocity) and when I get stuck the RealVelocity either oscilates between positive and negative values or turns completely into a zero vector. I assume neither should be happening, especially considering the Velocity still shows proper values?

viksl avatar Apr 26 '23 16:04 viksl

LOOK AT SOLUTION SECTION TO FIND OUT HOW TO FIX THIS PROBLEM:

I can confirm this still happens in version 4.2.1.stable.mono with a Capsule collision shape, but the jitter happens on the floor for me. This jitter goes away when the collision shape of the CharacterBody3D (that the Camera3D instance is attached to) is made a Box collision shape. The Y-value of the Camera3D that is a child of the CharacterBody3D changes much less when the shape is a Box instead of Capsule. This makes me think that it is the micro changes and oscillation between Y-values causing this.

You can find more details on the post I made here, with videos aswell, to show what is happening: https://forum.godotengine.org/t/my-camera3d-node-will-not-stop-jittering-up-and-down/56078

A fix for this would be amazing since a Capsule collision shape for the player's CharacterBody3D would be much better than a Box collision shape.

SOLUTION & EDIT:

I solved this problem by adding the else-statement below to my "gravity" if-statement:

else{
        velocity.Y = 0.0f;
}

To the this code block:

// Add the gravity.
if(!IsOnFloor()){
	velocity.Y -= gravity * 3.0f * (float) delta;
	stateDict["firstTouch"] = true;
}
else{
        velocity.Y = 0.0f;
}

This prevents any sort of change to the Y-axis value on the CharacterBody3D and the Camera3D child when the player (CharacterBody3D) is on the ground (IsOnFloor() == true). It seems that not resetting "gravity" back to 0.0f when the player was on the ground would mean the player's CharacterBody3D would be continually pushed downward into the floor, causing many collision checks and potentially causing the jitter if the player was forced down repeatedly into the floor and back up again.

ZenPyro avatar May 02 '24 00:05 ZenPyro

LOOK AT SOLUTION SECTION TO FIND OUT HOW TO FIX THIS PROBLEM:

I can confirm this still happens in version 4.2.1.stable.mono with a Capsule collision shape, but the jitter happens on the floor for me. This jitter goes away when the collision shape of the CharacterBody3D (that the Camera3D instance is attached to) is made a Box collision shape. The Y-value of the Camera3D that is a child of the CharacterBody3D changes much less when the shape is a Box instead of Capsule. This makes me think that it is the micro changes and oscillation between Y-values causing this.

You can find more details on the post I made here, with videos aswell, to show what is happening: https://forum.godotengine.org/t/my-camera3d-node-will-not-stop-jittering-up-and-down/56078

A fix for this would be amazing since a Capsule collision shape for the player's CharacterBody3D would be much better than a Box collision shape.

SOLUTION & EDIT:

I solved this problem by adding the else-statement below to my "gravity" if-statement: else{ velocity.Y = 0.0f; }

To the this code block: // Add the gravity. if(!IsOnFloor()){ velocity.Y -= gravity * 3.0f * (float) delta; stateDict["firstTouch"] = true; } else{ velocity.Y = 0.0f; }

This prevents any sort of change to the Y-axis value on the CharacterBody3D and the Camera3D child when the player (CharacterBody3D) is on the ground (IsOnFloor() == true). It seems that not resetting "gravity" back to 0.0f when the player was on the ground would mean the player's CharacterBody3D would be continually pushed downward into the floor, causing many collision checks and potentially causing the jitter if the player was forced down repeatedly into the floor and back up again.

I'm having the same issue but the solution is not a solution. My game has slopes. They don't work anymore at all with this solution. I also ha some very strange jittering using NavAgent3D. Had to add the following code to make it better. Movement looks very odd when reaching the target but it stops the jittering when reaching it. Still this code should not be necessary:

if target_position.x>global_position.x:
                        if global_position.x+velocity.x>target_position.x:
                                velocity.x=target_position.x-global_position.x
                else:
                        if global_position.x+velocity.x<target_position.x:
                                velocity.x=target_position.x-global_position.x
if target_position.y>global_position.y:
                        if global_position.y+velocity.y>target_position.y:
                                velocity.y=target_position.y-global_position.y
                else:
                        if global_position.y+velocity.y<target_position.y:
                                velocity.y=target_position.y-global_position.y

nerdnils avatar May 03 '24 04:05 nerdnils

LOOK AT SOLUTION SECTION TO FIND OUT HOW TO FIX THIS PROBLEM:

I can confirm this still happens in version 4.2.1.stable.mono with a Capsule collision shape, but the jitter happens on the floor for me. This jitter goes away when the collision shape of the CharacterBody3D (that the Camera3D instance is attached to) is made a Box collision shape. The Y-value of the Camera3D that is a child of the CharacterBody3D changes much less when the shape is a Box instead of Capsule. This makes me think that it is the micro changes and oscillation between Y-values causing this. You can find more details on the post I made here, with videos aswell, to show what is happening: https://forum.godotengine.org/t/my-camera3d-node-will-not-stop-jittering-up-and-down/56078 A fix for this would be amazing since a Capsule collision shape for the player's CharacterBody3D would be much better than a Box collision shape.

SOLUTION & EDIT:

I solved this problem by adding the else-statement below to my "gravity" if-statement: else{ velocity.Y = 0.0f; } To the this code block: // Add the gravity. if(!IsOnFloor()){ velocity.Y -= gravity * 3.0f * (float) delta; stateDict["firstTouch"] = true; } else{ velocity.Y = 0.0f; } This prevents any sort of change to the Y-axis value on the CharacterBody3D and the Camera3D child when the player (CharacterBody3D) is on the ground (IsOnFloor() == true). It seems that not resetting "gravity" back to 0.0f when the player was on the ground would mean the player's CharacterBody3D would be continually pushed downward into the floor, causing many collision checks and potentially causing the jitter if the player was forced down repeatedly into the floor and back up again.

I'm having the same issue but the solution is not a solution. My game has slopes. They don't work anymore at all with this solution. I also ha some very strange jittering using NavAgent3D. Had to add the following code to make it better. Movement looks very odd when reaching the target but it stops the jittering when reaching it. Still this code should not be necessary:

if target_position.x>global_position.x: if global_position.x+velocity.x>target_position.x: velocity.x=target_position.x-global_position.x else: if global_position.x+velocity.x<target_position.x: velocity.x=target_position.x-global_position.x if target_position.y>global_position.y: if global_position.y+velocity.y>target_position.y: velocity.y=target_position.y-global_position.y else: if global_position.y+velocity.y<target_position.y: velocity.y=target_position.y-global_position.y

Do with this what you will, but I found a solution for your case (and my case now) that still allows you to use slopes. It seems that the delta parameter is causing these oscillations between values that are small, but not small enough to be unperceivable to the human eye. So I use the delta parameter for everything EXCEPT manipulating the velocity.Y value.

So, disregard my earlier solution, and instead do this: 1.) Remove any sort of delta from interacting with your velocity.Y. 2.) Rejoice if it works for you too.

ZenPyro avatar May 03 '24 14:05 ZenPyro

Hm, I don't know if you noticed or already tried but check the jolt physics addon, you just need to add it to your project and in project settings switch to jolt from godot physics. It likely resolves all your issues. This plugin is a big talk when it comes to godot and physics and is pretty much expected to eventually be included in godot officially too at some point, many people have been using it for 3d physics for quite a while now.

viksl avatar May 03 '24 17:05 viksl

Hm, I don't know if you noticed or already tried but check the jolt physics addon, you just need to add it to your project and in project settings switch to jolt from godot physics. It likely resolves all your issues. This plugin is a big talk when it comes to godot and physics and is pretty much expected to eventually be included in godot officially too at some point, many people have been using it for 3d physics for quite a while now.

Wowowow! That is an amazing tip! Thank you for letting me know. My first question was going to be why they haven't implemented it into the engine yet, but you answered that too already haha.

I do have another question though, with the addon, is it as easy as dropping it into an existing project? Will it mess with any of the physics already implemented?

EDIT:

Godot-Jolt works excellently! It fixed the jitter issue without any sort of changes on my end. I definitely recommend using it until Godot comes out with some updates with their physics engine!

ZenPyro avatar May 03 '24 19:05 ZenPyro