Robustness and stability of physics interactions in Godot. A 4 years retrospective. #9646
Replies: 7 comments 10 replies
-
I would like to give my personal recommendation for @yosoyfreeman 's work. He's an incredibly self-motivated and passionate person. And the amount of work he's put into this is hard to believe. Dear Godot Team - please, hire someone to fix our physics. And make them work with @yosoyfreeman , because in my humble opinion he is the person to talk to about character physics in Godot and how to fix them. The more visibilty Godot gets, the more games are made with it, the more I see people saying "nice game, but the character movement is broken". We really need this thing sorted out. Badly. |
Beta Was this translation helpful? Give feedback.
-
Hey! I ported CharacterBody3D to Rust using gdext, maybe it makes things to fix easier to spot? Also it's easier to use GDExtension to mess with the character controller than recompiling Godot. https://github.com/lmsonic/RustCharacterBody3D |
Beta Was this translation helpful? Give feedback.
-
Is that possible to get rid of the broken Godot Physics (nodes and servers) and use GDExtension plus a third-party physics engine (like Jolt, Havok, or PhysX) to implement some new physic nodes from scratch for your need? |
Beta Was this translation helpful? Give feedback.
-
Hi, thanks for taking the effort of writing this large piece. To be honest, I don't really understand what the problem is. The only problem I can think of in the current Godot Physics is the collision code, which is kind of buggy. The problems are well understood but the fix is laborious. We already tried to hire someone to work on this but failed (no interest or anyone volunteering), and existing contributors did not seem interested in learning. Hence, if we are not going to find maintainers, at this point I give up and prefer we use Jolt, which will most likely be merged into the engine. |
Beta Was this translation helpful? Give feedback.
-
As side note, the way Quake does collision (as well as it may work) is completely obsolete and limited, so I would not bother comparing to it. It basically shifts the whole BSP tree by the size of the player, so ellipsoid collision is handled as a point. This means it only supports one collider type and size. |
Beta Was this translation helpful? Give feedback.
-
Hi Reduz, i appreciate your answer and time!
For what i came to understand there is no particular piece to blame. I think that a good way to explain is that we are using a resolution algorithm very similar to what you would use in a physic simulation, this meaning an overlap-resolve approach. So we detect an overlap and apply kinematic solving. This resolves the collision, but does cause a displacement from the original motion vector. More overlaps, more variables, more displacement, less performance etc. Because of this, sweeping is often the desired solution. I myself upgraded the proposal mentioned above that you made about using sweeping, but found out of my own experience and the talks with Mihe that does not really works, because we are still trying to figure out a safe an unsafe fraction and resolving in the unsafe fraction(Using SAT) if i remember correctly. As such, the benefit of doing the sweep that way are lost.
I have studied jolt, specifically the character part and talked long with @mihe about some this stuff on the Godot Jolt Github. He has done incredible work, and we got with some ways to improve how move and slide behaves right now, but i honestly think that's as far as we are going to go with the current approach. From what i understood, Godot should have the necessary methods to calculate a set of shapeVsShape intersections. Instead of getting contact points by forcing overlapping, once you we the body at ToI 0 the closest points between the shapes are our contacts point. This would allow us to also get surrounding information by a a margin, (Often called the offset or the shell) to both gather information about the environment for the character and guarantee it's stability. I's certainly a lot of work, but the problem remains in that, even if Mihe does all that work(Because i would perfectly understand he is not willing to do that for free) we still want to wrap it into a friendly node, unless we surrender completely and also use the jolt character controllers. Honestly, i think the biggest problem right now is uncertainty. In all the cases, making jolt official would finally give some security to work on. It's very hard to make improvement to Godot Jolt in this sense because as things are right now, everything that is built in in the Godot side must work in Godot jolt to keep feature parity. And some time improvement on Jolt side make's things worse on godot side because some behavior (The character controller specially) has some hacks that depends of features not working fully correctly. I only speak for myself and the hours i pour into this, but with all respects, its been various months since i was asked what else was needed to test or account for in order to advance in making Jolt official. I know its a hard problem, maybe we don't get a full solution soon, but in my humble opinion focusing a bit on that regard could drastically improve the situation on the long run. If Godot jolt is official probably more people will know of it, and perhaps help tackle this issues with a renewed spirit. Step by step is how the path is done. Thank you again for your time, i really mean it. PS:
This is absolutely true! However, the same "version" of this algorithm has evolved since then and is present In engines like source 2, Unreal, or unity (This very simplified). It also present in physx, bullet and Jolt itself. What has change is how you get the information, but the overall concept is still the same. Sweep, gather, resolve, iterate. |
Beta Was this translation helpful? Give feedback.
-
Hello there! I been working with Godot since 3 almost exclusively on the development of character controllers, movement systems and game-play mechanics related with traversal for more than 4 years now and i would like to recapitulate about how this experience went, the issues i found, possible solutions and remaining problems. I'll try to keep this organized and concise, but please, have in mind this the result of various years of work and therefore there is a lot to cover. My intention here is not to link to every issue ever reported, but to hopely provide some useful information about the experience of working ins this kind of systems as a whole.
What is this shiny thing?
Once upon i time i was a developing games with archaic SDK's as everyone else. Mos of them were some combination of a 3D engine, and scripting system and some tools that were used to create maps. A new thing called Unity suddenly arrives and is very similar in concept, but instead of having all this different pieces tapped together people started to get familiar with the concept of a game engine that we have today. Sure, why no? I thought. It was, at the time, not much better in terms of graphics (Even worse than some tools 5 years older in some cases). I used unity very happily for years, until i saw that new features were constantly added without finishing the ones that came before or doing an analysis of why the older tool failed in first place. The engine start to bloat while no real benefits are added, long lasted issues were never addressed and, as a result, some of the Unity talented devs started jumping out the boat. This was enough indication for me to know that i should prepare myself for a change.
I go and jump to UDK 3. Surprisingly, i don't miss anything. It has less features, but the ones it has are solid as a rock. I did the jump as soon as the Unreal 4 beta came out. I used it for various years too, until again, it became too bloated for different reasons. It was still a great engine, but new features were, with an increasing frequency, aiming more and more towards triple A and the film industry. As a solo dev, i felt like Unreal was doing too much for me and preventing me to learn Game development itself while being increasingly slow because of features i would never use. I started again looking for something smaller, solid, and focused on the indie market. But nothing was really there... So i kept waiting. What i didn't knew is that i was in fact, waiting for Godot.
First steps in Godot 3.x
So, this little engine that i been following for a long time and telling myself "It it had the most basic 3D features i would jump right now" just dropped one. I waste no time and download the thing.
The first thing i like is the renderer. No, I'm not crazy. It is really quick and clean, and it does not take 45 minutes to compile the required shaders for an empty program. I see it lacks any kind of level editing tools, which is something i miss from every single toolkit or engine i used, but I assume that is coming and start learning the thing. Spoiler, is not coming. Even being one of the most requested features at that time and long conversations taking on, it seems like a level editor is not general purpose enough. some don't understand how the ability to create the fundamental 3D shapes you will be interacting with
in a 3D game is not general purpose (I included). Blender is suggested instead. The ones who have used blender, specially at that time had one thing clear: Blender is not a level editor and trying to make it work like one is painful. Blender is not even a 3D modeller, is a fully fleshed multimedia creation tool. Perfect to create assets, or tileable kits if you have the time or the team to produce them, as they are not a great way for indies to work with (In godot, using them is specially hard because of physics issues, but we are jumping ahead) . In any case, a great tool called Qodot allows to use trenchbroom to create levels and for the time I'm versed enough with GDscript i can import my levels without issues in Godot.
Lets do something simple
For the surprise of no one, the community is full of people who thought the same thing: "We have a decent renderer that will be great with some tweaks and better lightmapping, and now we have a tool to import quake maps. Let's do quake in Godot, is a new engine and quake is easily reproducible"
A lot of people did great ports of the quake movement system, some of them 1 to 1. But we all had the same issues. No matter how much you polish the code, the information provided by the limited physic API seems erratic and unreliable. Collision normals point in the wrong directions, the character gets constantly stuck, and the collision resolution is constantly making the character slide against any surface, in some cases, even when there is no velocity being applied. After some months some of the most advanced people has lost hope in making move and slide work and have started creating their own sliding algorithms from scratch following any of the publicly available solutions from Quake or the source engine.
Still does not work. Some manifestos from experienced people start to appear such as the famous Shifty's Godot Character Movement Manifesto
Lets talk about move and slide
After all that time working on it myself and gathering the experience of other issues, i made a post on the Godot reddit called Lets talk about the actual approach for move_and_slide, is_on_floor() and collisions problems. . You can read it yourself for more details, but in short terms, the answer was that it was fault of the physics engine Bullet, because it was not meant to work for games and had a lot of issues (I feel the necessity of pointing out that bullet is still being used in games that require extreme control of the physics environment without issue). We were also told that, in fact, all of this was working wonderfully with Godot physics (it was not, as we kindly suggested various times). Lets break this answer down, having in mind that we are talking of issues present more than 4 years ago.
It does not work well with Godot physics. I feel like i don't need to defend this point at this moment of time.
First of all, all my respects to the work of Andrea, the creator of the sliding algorithm at that time. In fact, he later created exponentially better solutions for his own game in Godot, but sadly this improvements never reached the engine. (Examples here, here and here ) This said, i think is very important to understand this part.
Here two different concepts are mixed into one: The way in which we retrieve the information from the environment and the way in which we react to that information. First, movement algorithms are indeed complex, however it is very far from being an "extremely difficult to understand algorithm", specially having into account how limited the implementation was in that time. I'll take about this in more depth later but for now lets say that there is, as i said before, a lot of examples about how to integrate this, from the good old days of quake, going trough source, up to the most recent jolt engine.
The problem was not the complexity of the algorithm, but the fact that it was (and keeps being) limited to react with one plane at a time. This will inevitably lead to problems in acute corner scenarios, recursive behavior, and situation in which a new valid velocity can simply not be calculated, causing the next iteration to get stuck or stop all together.
This behavior is not present in older games because this case was handled correctly, however, i think is safe to assume that our solution is based on the paper Improved Collision detection and Response by Kasper Fauerby. This paper covers the topic of an sliding algorithm on the context of a triangle soup and is similar in concept, however, in this case, the paper focus itself on how to handle this situation against a triangle soup. This covers the complex math of gathering the information and a simple sliding behavior to prove it which is only able to react with one plane at a time.
It was never meant to be used as it is. However, people did and is still doing it today. As you may have figured by know, we said that is not possible to properly react to collisions with just one plane without incurring in the problems i mention. In fact, none of the examples i used, not even quake being the oldest one limits its resolution to one plane as you can see here.
So, why we got a a bug that we never had in first place? Because this paper is clear, is well explained and is meant to be educational. Is easy to access and easy to understand specially compared with digging source code for answers, and as such this paper is named incredibly often on the indie industry.
Some time later, a new paper appeared called Improving the Numerical Robustness of Sphere
Swept Collision Detection by Jeff Linahan. This paper tries to improve upon what is presented on the original one and tries to address what they called the numerical robustness of the system. In this paper the acute case scenario is well explained, however, the way in which is fixed is wrong and this extended too.
This paper presents a truth that was already taken in consideration in quake. The axis of freedom left decrease with the amount of collisions. The problem? It claims to have improved the max number of iterations up to 3. How? Misunderstanding the purpose of the original algorithm, it assumes that every plane we wit along the travel extends infinitely, so after 3 hits all degrees of freedom are always lost. This, of course, violate the temporal cohesion of the algorithm, because is very possible that the second collision happens after some movement and therefore the plane that was blocking us on the previous iteration is no longer there, but we are reacting like we are still blocked by it, and not only that, it assumes that the new velocity always violates the previous planes,, while in reality this is not always true. If the character is sliding in the inside of a cylinder, the first collision would lead it to a curve that would not violate the normal, nonetheless, with this "Fix" the body would stop the circular motion at the second hit, breaking the continuity and physical logic of the movement. A partial implementation of this fix is what Godot uses today and the reason of lots of unexpected behavior the users face. This can be seen clearly on this line.
Proper methods for multi plane resolution are, again, available since quake. Quake has an outer loop and and inner loop. The outer loop will try to resolve the velocity against the first plane on the array, and then the inner loop check if this new velocity violates any other collision plane. If it does, this velocity is not considered valid, the inner loop breaks and we resolve against the next plane and repeat the test.
If the new velocity does not violate any other normal, is valid. If we finish processing all the planes and the velocity still push against a normal, then the cross product of the two last planes are used to project the velocity into the crease vector. Variations of this method are freely available, including Jolt character virtual.
So, it is not an "extremely difficult to understand algorithm". It is on the second part that he is right. This is "In part" due to how bullet handles collisions...
The problem is that we should never be trying to use a physics engine approach to collision resolution in first place, unless you collision resolution is almost magical, a thing we can agree we don't have. In all the cases i mentioned and some more: All the quake games, all the source games, titanfall, apex legends, unreal engine or unity do all use swep/sweep testing for this. That's the reason Arbitrary triangle shapes are not possible to use for character movement in most engines. Because even if you nail the algorithm, you can not realistically expect nothing of this to work without extremely precise and reliable information. And just to be clear: Move and collide or test move are not equivalent to a sweep test, nor in precision or functionality. It is not acceptable be displaced out of the motion vector in any case, and even enabling p_cancelslide is far away from working for this purpose. Move and collide will stop you if you are inside of a face, which should never happen, because in all cases going trough geo is better than getting the character totally frozen because a single time we had the bad luck of it resolving the body inside a face. And even worse, because the process is iterate and then resolve, we can end up tunneling through geometry or in the worst case scenario (Which is almost every case) getting reports about collisions that are impossible to occur. This is what causes most of the problems of getting stuck or "sliding along edges". Even a crease on the floor can be reported as a wall, even thou the body could never move to the collision point because it would be blocked by the floor collision that is reported too and goes first!
Essentially, this problem is born on the design stage and we are trapped inside an XY problem. We can try to improve the sliding algorithm all we want, but a perfect sliding algorithm will react to bad information too, and before that is corrected nothing can be done to improve on it.
To remember point 5:
Exactly. Because the problem is not only the sliding algorithm or the physics engine. The problem is on the tools we use to make that algorithm work.
The next part of the response goes like this:
With all my respect, i really hope that, at this point, time has provided us some perspective about how underestimating a problem can make bigger.
I don't think there is a lot to say here, i think everyone know that physics engines are indeed very complex, and that Godot physics does not get most of the job done.
I think that 4 years later we can agree that it was not a matter of "just fixing some issues, optimizing and adding softbody support"
The official solution ended up being... none.
At this point i been 4 years working on this. Implemented not only one, but different sliding algorithms, learned everything i could to help tackle this issue, reporting bugs and trying to get that help that he is talking about. I never got it. Not me or everyone else.
I want to be extremely clear: I Admire Reduzio as a developer, i think his contributions are great, and this is not in any kind of shape any kind of personal problem. I honestly believe he just underestimated the issue by various orders of magnitude. The problem is that he has refused to accept neither the magnitude or the implications of the issue and at some point i believe he started thinking that a new physics engine in the form of a extension, by itself, would solve the problem. Again, an XY situation.
However, inaction is a tricky. As time goes on and more tools rely on the current toolset and doing custom workarounds for this issues, the harder it will be to take a step back and revise our foundations.
So, what has improved in this 4 years?
In what is related to character controllers and the original problem, nothing. Godot 4 introduced a new version of the kinematic body on the form of character body, with two different versions, grounded and floating, and merged a lot of the features to the node, making harder to create custom movement. As a result, the problem got even bigger: Move and slide is now more complex and less people understand how it works. It is now tightly coupled to other systems too, such as reacting to other bodies or moving plarform. All of this only works "as intended" if you limit yourself to the horizontal plane, because the vertical velocity is not even calculated and platforms will have troubles working if you wish to have at least the same amount of control you had in Godot 3. None of the issues that started this conversation 4 years ago were fixed along the road.
Collision resolution still works one plane at a time. The "fix" that will stop valid motion if two walls are hit is still there. There are still no methods to do proper swept test, or at least something solid enough to accomplish the minimum viable product, so any algorithm will keep failing. Still, gathering simple information about all the contact planes is not possible in a solid way and the next best thing is get rest info, which only provides one collision normal from a shape, so it can not be used to resolve collisions.
Poetically, the same engine who thought creating 3D shapes was not general enough, ended up with one of the most specific controllers out there.
What are your recommendations?
I think they are already clear in this post and all the years i been working on this for the love to open source and this community. I honestly think the problem is harder to fix now and it will become increasingly harder as time goes on.
This was something that we could have addressed together as a community, with the uncountable people who tried to help but never got any answer, or who's problems or proposed solutions were diminished once after another.
At this point i have only one recommendation: recognize the problem, give it the priority it really has and -HIRE- someone to fix it. Godot has been in position to do this multiple times, in fact it had it easier that any other small open source tool out there. Just use some of the founding we got for the engine to fix the biggest and long lasting issue in the engine. I think is reasonable.
But have you tried Godot Jolt?
As i said, this is not something that gets fixed by plugin in another physics engine. But yes, since it was announced i been testing, isolating and reporting bugs to it, as well as doing what i could to improve collision response on that side. It's creator has been really active and had taken care of almost everything i can think of.
How much i tried to promote jolt? well, i was the second person to participate on the conversation in jul 19, 2023, and i'm the last person who did it on Dec 07. Not a single answer has been given since yet.
Do you hate Godot?
I love it.
Do you hate the team?
Of course not!
Do you think Godot is very bad and nobody should use it?
No, i think Godot is the more promising piece of software i seen in my life and participating on making it grow when it was starting in 3D is something I'm proud of.
I think there is a giant four dimensional ultra violet elephant in the room, thou.
I want this to get the attention it deserves so me and everyone else can start enjoying the engine instead of fighting with it.
Hire someone. Really. Please.
What now?
More than four years ago i started full of joy a little project. I wanted to make quake... In Godot!
is been four years of not only that, but participating in everything i could too. Non stop.
I'm just a little bit tired, and close to trow the towel. But then i remembered who much i love this community and chosen to do what i did four years ago with the hope of child. Have a little conversation and talk about the future.
Been waiting for Godot more than 4 years and quake is just as far as it was.
Once upon a time i wanted to make a little project. I wanted to make quake... In Godot!
Now i think I'll spend some time playing it.
With all the love and passion i have for this community and towards everyone who puts its grain of sand into this giant and beautiful castle that we are building,
Freeman.
Beta Was this translation helpful? Give feedback.
All reactions