godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.07k stars 69 forks source link

Refactor Physics3D nodes #5003

Open Diddykonga opened 1 year ago

Diddykonga commented 1 year ago

Describe the project you are working on

Godot

Describe the problem or limitation you are having in your project

The current implementation of Physics3D Nodes:


- CollisionObject3D #Base class of all Physics Objects
--- Area3D #Base class of all Physics Areas, with everything about Areas exposed
--- PhysicsBody3D #Base class of all Physics Bodies
----- PhysicalBone3D #Physics Bones, used in Skeleton3D Animation
----- StaticBody3D #PhysicsBody3D, but in STATIC BodyMode with exposed constant velocities
------- AnimateableBody3D #StaticBody3D, but with sync to physics implemented
----- CharacterBody3D #PhysicsBody3D, but in KINEMATIC BodyMode with a high-level implementation for Characters
----- RigidDynamicBody3D #PhysicsBody3D, but with everything about the Body exposed

Any use of StaticBody3D, AnimateableBody3D, CharacterBody3D, PhysicalBone3D or RigidDynamicBody3D was a Rigid Body on the Physics Server anyways, but these classes chose to only expose certain properties of that Rigid Body, which would often cause many new users to wonder if they were separate things, often causing issues when the user seeks to have a functionality from one in the other, not knowing they are indeed the same underlying object/type.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

The refactor of Physics3D Nodes:


- PhysicsObject3D #Base class of all Physics Objects
--- Area3D #Base class of all Physics Areas, with everything about Areas exposed
--- Body3D #Base class of all Physics Bodies, with everything about Bodies exposed
----- SoftBody3D #PhysicsBody3D, but with everything else about Soft Bodies exposed (This will be a pain to separate from rendering)
----- RigidBody3D #PhysicsBody3D, but with everything else about Rigid Bodies exposed
------- Bone3D #Physics Bones, used in Skeleton3D Animation
------- CharacterBody3D #RigidBody3D, but in KINEMATIC BodyMode with a high-level implementation for Characters

sync_to_physics: Moved to PhysicsObject3D to support Syncing to Physics as a core feature of all Physics Objects. StaticBody3D: This node was incredibly simple and can be recreated with a RigidBody3D and setting BodyMode to STATIC. AnimateableBody3D: With Sync to Physics being changed to a core feature of all Physics Objects, there is no longer a purpose for this node.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

The goal is the simplify the Physics Structure in Godot, and make it easy to teach and easier to understand.

Physics Objects we have for Godot:

Body can have two types: RigidBody and SoftBody RigidBody can have four modes: STATIC, KINEMATIC, DYNAMIC, DYNAMIC_LINEAR

- (LEGEND)- PVI = Physics Velocity Integration (Updates position with velocity) PFI = Physics Force Integration (Updates velocity with forces/user-code move) PS = Physics Simulation (Default Physics PVI/PFI Implementation)

With this proposal all users will be covered by RigidyBody3D and creating user-derived types/scenes from it, to implement higher-level functionality while knowing the RigidBody3D is a proper medium-level type and fully exposes the underlying low-level interface.

If this enhancement will not be used often, can it be worked around with a few lines of script?

This a core structural/implementation change.

Is there a reason why this should be core and not an add-on in the asset library?

This a core structural/implementation change.

Calinou commented 1 year ago

Related to https://github.com/godotengine/godot-proposals/issues/2184.

I think this is too large a scope to be done for 4.0. We should only do minor adjustments from now on, or anything else will take too much time to bikeshed on.

Diddykonga commented 1 year ago

I think this is too large a scope to be done for 4.0. We should only do minor adjustments from now on, or anything else will take too much time to bikeshed on.

That's fine I understand how late this is, and will take some time to bikeshed as you pointed out. Although hopefully for 4.1, as I believe that will be the last chance to do any compatibility breaking that this would require.

SilencedPerson commented 1 year ago

I think having static bodies as a separate is still very worthwhile... though I can't really remember the last time I actually used it. I just press the button that generates colliders for me.

Diddykonga commented 1 year ago

I think having static bodies as a separate is still very worthwhile

StaticBody3D: This node was incredibly simple and can be recreated with a RigidBody3D and setting BodyMode to STATIC.

If this ^ makes something worthwhile, then we are doomed.

Zireael07 commented 1 year ago

StaticBody3D: This node was incredibly simple and can be recreated with a RigidBody3D and setting BodyMode to STATIC.

I can't think of an engine where you DON'T have a StaticBody of some sort since it's so extremely common an use case. It saves users several clicks.

Diddykonga commented 1 year ago

I can't think of an engine where you DON'T have a StaticBody of some sort since it's so extremely common an use case. It saves users several clicks.

While I still think that you are overthinking it, since they are many other nodes that you must setup first before they are proper for your use case. Either way I digress and would suggest BodyMode be STATIC by default when creating a RigidBody3D. This way if you spawn a million for some odd reason, they wont all be DYNAMIC if you forget to set the BodyMode.

Mickeon commented 1 year ago

I think having static bodies as a separate is still very worthwhile

StaticBody3D: This node was incredibly simple and can be recreated with a RigidBody3D and setting BodyMode to STATIC.

If this ^ makes something worthwhile, then we are doomed.

Watch your tone. Firstly, yes, it most definitely does make it worthwhile, in a game development context, especially a game development context designed to be easy to access, quick and easy to start developing with. With such an argument, it could be said that VisibleOnScreenEnabler shouldn't be a class, either, because it's easy to set up using VisibleOnScreenNotifier as a base.

Secondly, there's one very important thing. StaticBodies are always static. They'll never not be static. Oftentimes, these nodes are unmoving, as well. It's a major open door for optimisation.

TrialDragon commented 1 year ago

I agree with @Mickeon regarding StaticBody. By having the body as a separate type to the RigidBody then a user can have the assurance of single-use, that a scene using the StaticBody won't just suddenly start acting dynamically out of the blue because somewhere the mode was changed. The same could be said for KinematicBody and a DynamicBody; they would each provide assurances that they won't suddenly start acting like the other because of one wrong flipped switch. Perhaps that is a pedantic worry, but Godot does aim to follow SOLID if I remember correctly.

It'd also be more intuitive for any new Godot user who is not versed in physics or industry terms to figure out and remember StaticBody does not move, DynamicBody is moved by physics, and KinematicBody is moved by code. Rather than RigidBody is the physics body for solid things, named after a term they may never have been exposed to, and has modes for not moving, moving by physics, moving by code, and whatever dynamic-locked connotates-- I never had to look into it to find out. So it makes sense to me to have those 3 subset bodies alongside the main RigidBody.

Diddykonga commented 1 year ago

What both of you are pointing out is that a StaticBody is assumed to always be Static, but in reality the low-level Physics Body can be switched to either mode, so at any time an StaticBody may be Dynamic. Either a change to the low-level PhysicsServer for creating distinct body types and not allowing changes should be made or otherwise, this is not doing what you expect.

What I am suggesting is a change that more accurately represents the interface that the Nodes are built to expose to users in the Editor. I really can not understand the requirement for not changing a enum property on a Node you add to a Scene to get the functionality you want, as there are multiple examples of this throughout the Engine.

TrialDragon commented 1 year ago

That is true, the argument on my end for single-use and presuming it is always static is admittedly a weak one. Though the having of StaticBody and other nodes representative of RigidBody nodes were less to be representative of the underlying system but rather useful abstractions of that underlying system for, albeit potentially minimal, ease of use in ways. There is definitely a valid argument for trying to expose the base physics server RigidBody API only accurately. Though with my argument I feel that RigidBody should be a node ideally for that reason; an accurate exposing of the physics API underlying for more complex uses, whilst the three nodes representative of RigidBody's main modes are there for ease of use and shortcuts.

I still think it's easier and more intuitive for new users to have KinematicBody, DynamicBody and StaticBody in addition to RigidBody rather than just RigidBody. For those unfamiliar with standard terminology, I noticed in my research on this topic-- primarily going through the Reddit poll for the RigidDynamicBody rename-- that many who weren't exposed to prior terms through either education on physics or prior experience with game engines found RigidBody to be too specific to those specific realms of expertise to be immediately recognizable or memorable to them in relation to learning. So whilst maintaining the industry standard of having a RigidBody for good reason it also makes sense to have the aforementioned trio of nodes to ease newcomers to game development by giving them more specific to their use nodes that can have better memory correlations.

However, having those three nodes are not a dealbreaker; I still consider this refactoring an improvement over the current organization regardless of what I suggested to potentially improve it. After considering what @Diddykonga has said in their messages; there ultimately isn't really much of ease of use boon, other than having them be potentially easier to learn as said in the prior paragraph. In regards to what @Mickeon said about optimization, is that actually possible considering that afaik StaticBody is effectively just exposing the physics server RigidBody in static mode? That is to say wouldn't any potential optimizations be already included in either way since they're both the same underlying thing? Or is it meant that StaticBody would not need to contain any logic to make a kinematic, dynamic, or dynamic-linear mode work node-wise?

Diddykonga commented 1 year ago

Optimizations for RigidBodies in Static BodyMode is done currently.


So you have the medium-level Nodes such as RigidBody that I am suggesting, that simply expose the underlying low-level system/server that they are based on, which gives easier access to the general use cases the low-level system/server provides.

Then you have high-level Nodes such as CharacterBody that further exposes a medium-level Node(or potentially low-level if no medium-level makes sense) to provide deep functionality for specific use cases.

All StaticBody, KinematicBody and DynamicBody do is set BodyMode enum, they don't provide any other functionality as compared to CharacterBody for example, which should be kept.


As for the teaching/learning aspect, I would agree although I'm not confident that Kinematic is a very well known term either. The way I look at it, is that the documentation for the Physics Bodies just needs to be improved to properly explain the hierarchy and systems in play, which I attempted to break down in the OP.

TrialDragon commented 1 year ago

Hmm, yeah I'd say I overall agree with that. Especially the whole Kinematic not being as well-known, issue; I noticed it too a few days ago and I've been trying to think of good solutions for it. Like, there are a few thoughts I've had on that.

  1. Have a 'high-level' KinematicBody node that has some extra stuff compared to RigidBody for stuff such as moving platforms with code; basically it's the one that has move_and_collide and such simulated motion helpers. This is a bit unclear because of the fact that kinematic may not be a well-known term potentially, and I guess one argument against it compared to 2 is that it may limit developer creativity.
  2. Follow the philosophy of the PhysicsBody node reorganization and have such kinematic / simulated motion helper aspects be in the RigidBody node so that everything is effectively kinematic. This may make the most sense
  3. More a variation of the 1st one, but perhaps also give the KinematicBody a static and dynamic physics mode so that it can be used to move objects of both physics types with code. The only benefit of this over 2 is that you can potentially mix static and dynamic movement of the object for unique movable things, like a prop hunt mechanic-inspired game, though I have no clue how that could ever be cleanly implemented. This is more of a weak random idea that popped in my head and wanted to get out, highly unlikely this one is a good idea.
Diddykonga commented 1 year ago

1. 2. 3.

  1. There really is only so much you can do with a Physics Body, so unless it was specifically a MovingPlatformBody or something, that had a deep(?) implementation for specific use cases then maybe, although I am not 100% certain as to whether this should be a high-level node, since I am not sure how deep of an implementation you could provide that would require the code to be C++ for speed. I have thought for awhile about introducing Engine Content into Godot, as it is one of the things that I miss from Unreal, where Engine Developers could provide Assets that come as part of the Engine, which the MovingPlatformBody could be a Scene that comes with the Engine Content, to be either used directly or learned from.

  2. This is the plan currently, to move all Body-Wide helper methods to RigidBody, and potentially in the future to PhysicsBody, if we are able to figure out what all Rigid and Soft Bodys have in common.

  3. This is basically a RigidBody in Dynamic BodyMode, as a Dynamic Body can still be moved by the user, while also effected by the Physics Simulation. Although you must do it in _physics_process()(?) or _integrate_forces(), which isn't technically required for non-Simulated BodyMode's.

TrialDragon commented 1 year ago

So, do we agree that DynamicBody and StaticBody should exist, presuming numerous others also agree, for teaching/intuitive reasons for beginners or those new to Godot? That there is no need for KinematicBody since it should already be handled by RigidBody, or potentially PhysicsBody if applicable?

Diddykonga commented 1 year ago

Personally, I disagree, simply because of how basic they are, and this type of thing really should be handled via good documentation + examples.

All types are covered by RigidBody Node, which you can set it's BodyMode to be either a Static, Kinematic, or Dynamic(-Linear) Body.

TrialDragon commented 1 year ago

Alright. Well to be honest that is fine. I can kind of see your point of view now, and the one I'd been arguing very well could've been biased and weak for reasons currently unknown to me given I am now not finding much of a solid argument on my side, in comparison to before, at this point. So presuming no one else actually has good reasons in regards to having those other bodies then I am at present fine with just RigidBody.

Diddykonga commented 1 year ago

For High-Level Nodes, to me it comes down to how much code/effort-in-editor would it take for me to recreate that Node if it didn't exist, For example, CharacterBody3D would be quite a bit of code and would also run slower in GDScript. Where as, StaticBody3D is the default RigidBody3D(I believe Static BodyMode should be default), and DynamicBody3D is a RigidBody3D with BodyMode set to Dynamic. Which doesn't reach the threshold for Node-ification.

golddotasksquestions commented 1 year ago

I find this proposed structure miiiiles more clear and therefore much more preferable than the current one in Godot4 Alpha14.

However I do have some problems with this proposal too, especially with defaults and behaviour:

Either way I digress and would suggest BodyMode be STATIC by default when creating a RigidBody3D.

This just sounds like a very bad idea, as it is super confusing: By default you expect a RigidBody node to be able to move. Making it STATIC by default is already confusing. Then allowing it to move under certain circumstances despite it being in STATIC mode: super confusing and weird! This does not sound much better than what we have right now in Godot4 Alpha14.

I would expect RigidBody to have default mode set to DYNAMIC.

CharacterBody is a misnomer! This node/mode will be used for way more than characters. If your goal is to make things less confusing, stop using that name! KinematicBody is well established for this type of behaviour, even outside of Godot or the games industry.

Imho, StaticBodies (or RigidBodies in STATIC mode) have no business moving. That's why they are called "static"! In my opinion, they should be entirely passive. Rigid and Kinematic bodies can collide with them, but StaticBody can't bulge.

KinematicBodies (or RigidBody in KINEMATIC mode) imho has no business being moved by physics forces, that's the job of the RigidBody DYNAMIC node/mode.

The DYNAMIC_LINEAR makes no sense to me. If the only difference to DYNAMIC is the option to make it axis locked, why not simply expose this property to DYNAMIC mode as it is right now in Godot3 RigidBody? If there is some other reason why this extra mode exist I currently just don't see, I would rename it to DYNAMIC_AXIS_LOCK, since this would actually describe what it does. DYNAMIC_LINEAR sounds to me like forced linear acceleration, which this is not.

I think having a single node with very clearly defined modes which purpose does not overlap has a lot of benefits compared to the current Godot4 Alpha 14 system and even to the Godot3 system. Especially because this would allow to seamlessly switch an object from one behavior and type of user control to another.

@TrialDragon

By having the body as a separate type to the RigidBody then a user can have the assurance of single-use, that a scene using the StaticBody won't just suddenly start acting dynamically out of the blue because somewhere the mode was changed.

Being able to switch between distinctive single purpose modes at any time is exactly what is missing and what is only partially working in Godot3.

In Godot3 you already can switch between KINEMATIC and RIGID modes for RigidBodies. The problem is you can't control the RigidBody like you would a KinematicBody, when the RigidBody is in KINEMATIC mode. Which makes is pretty almost useless for countless gameplay applications. Most predominantly for Ragdoll-Like behaviour. In Godot3 you can't simply switch between KinematicBody and RigidBody (for example in mid air flight, or when the player lost control of their character). You can only lock an axis, but you can't use the KinematicBody move_and_... methods.

Which means as a designer I can't switch between intentional-driven entity control and driven by physics simulation at will. The only option is to completely replace the whole entity (since the physics behaviour is usually done in the root node) with a different one, which is an invitation for all kinds of bugs and performance issues (you will have to make sure to enable and disable everything). If switching behaviour could be done with the same root node, this would make highly dynamic fun physics simulated gameplay combined with precise user input controlled gameplay a breeze compared to now.

Diddykonga commented 1 year ago

However I do have some problems with this proposal too, especially with defaults and behaviour:

RigidBody BodyMode can be either STATIC or DYNAMIC by default, I care not which, that is for others to discuss. RigidBody BodyMode could do without DYNAMIC_LINEAR, in favor of generic linear/angular axis-lock flags. CharacterBody makes sense, in that it is a specific implementation of a RigidBody in KINEMATIC BodyMode, that is intended for use with Characters. This has support for things that a Character would want, and that other KinematicBody use-cases might not need, it is high-level and meant for specific use cases where it fits. If move_and_slide() is what you feel should be base, then that could be discussed.

YuriSizov commented 1 year ago

We have discussed the general state of the physics nodes in the bikeshedding meeting. We've agreed to drop the Dynamic qualifier from both rigid and soft bodies, so that the terms match the terminology that is most familiar across different engines. We can still have "dynamic" as a keyword in the documentation to help look up the relevant methods, once we introduce the keyword system to the documentation.

We don't plan to make any further changes to the physics nodes for 4.0. All previous discussions had a lot of people happy and unhappy about changes, so it doesn't look like there can be a universally good stack that satisfies everyone. Or at least one hasn't been found yet. Maybe in Godot 5... But for now, changing it back and forth, especially so close to beta, doesn't look like a good idea. Especially given we don't have many physics maintainers at the moment to make a good educated decision for the area.

I won't close the proposal, so feel free to deliberate further, but we won't be considering more structural changes for Godot 4.

Diddykonga commented 1 year ago

we won't be considering more structural changes for Godot 4.

Sad to hear, I guess I will be back for Godot 5 then.

mournguard commented 1 year ago

CharacterBody is a misnomer! This node/mode will be used for way more than characters. If your goal is to make things less confusing, stop using that name! KinematicBody is well established for this type of behaviour, even outside of Godot or the games industry.

Been looking for the proper place to say this. As someone starting to learn directly with 4.0 this is not only very confusing (As with that, not a single node is named KinematicSomething), but also incredibly opiniated in the worst possible way. Things should be named according to what they do not according to whatever someone thinks it should be used for.

Not experienced enough in the engine to debate on which bodies there should or should not be, but this name definitely has to go at some point.

ettiSurreal commented 1 year ago

I am all for going with this or a similar approach for the structure, looks very simple to understand. Especially if it lets you easily change body modes and it just working without having to write much extra code for separate modes. Could be useful for making things like simple grapple hooks on kinematic characters using joints.

DYNAMIC_LINEAR: PVI, PFI, Moved by PS and user-code, rotation locked for use with Characters

I feel like just adding a separate bool that lets you lock rotation is a more intuitive approach

Reading the discussion, it seems like the main problem people have with this approach is the possible unintuitiveness of the naming and proposed default settings, and that some people would prefer to have separate nodes just to save a few clicks when creating them. This could potentially be solved by adding a node preset system (something I've been planning to make a proposal for), and renaming the node to a more overall term like PhysicsBody, with Rigid/Kinematic/StaticBody being its presets.

Shadowblitz16 commented 1 year ago

It would be nice to make the 2d physics system consistent with this 3d one

ruanrothmann commented 9 months ago

I was considering opening a new issue, but I think my problem is encapsulated here.

Another problem this setup presents is that PhysicalBone3D does not expose certain propertied or methods that exist in Rigidbody3D (for instance, apply_force() and center_of_mass are two that have come up).

'sleeping' is also missing as a property, though it must exist, because can_sleep exists.

It is odd that PhysicalBone3D does not extend Rigidbody3D to me, what is the reason for that?

Calinou commented 9 months ago

It is odd that PhysicalBone3D does not extend Rigidbody3D to me, what is the reason for that?

See comments in https://github.com/godotengine/godot/pull/44150 and https://github.com/godotengine/godot/pull/58658 for rationale.

We can backport individual RigidBody3D properties to PhysicalBone3D as done in https://github.com/godotengine/godot/pull/82449.

ruanrothmann commented 9 months ago

In active ragdoll games, we will really have use cases for all the rigidbody3D properties and methods.

I am using apply_centra_impulse (force * delta) to approximate apply_central_force. But I also have a need for apply_central_torque, is_sleeping and get_colliding_bodies.

The biggest roadblock I have right now however is the lack of signals such as body_entered. Is there perhaps a simple workaround I'm missing for that?

edit - should I create a new issue for this?

Calinou commented 9 months ago

edit - should I create a new issue for this?

Yes, as this proposal can't be implemented without breaking compatibility (while adding new methods/signals to PhysicalBone3D can be done).

ruanrothmann commented 9 months ago

Added https://github.com/godotengine/godot-proposals/issues/8008

Shadowblitz16 commented 1 month ago

I would like to see the following done...