Hello community!

So, I am still pretty new to Godot, but I try to learn quickly so I can lay out porting my project, which currently exists in which-shall-not-be-named, to Godot.

Said project has many objects (hundreds) the player can interact with: Grabbing and moving them around, performing actions, modifications, etc. These objects can have different ways they behave, so I am planning to have a base - say "interactable" - which all the different object types inherit from. So when different functionality is required, I can extend the script of the interactable, add to the node structure as needed and it should work fine.

But there is one tiny exception: The vast majority of these interactables will all be a StaticBody3D as their root as they sit still and only need to provide collisions for Ridigbodies. Yet, said Rigidbodies are also meant to be interactables. And I believe this throws my inheritance idea out the window. At least I think so. From what I know (please correct me if I'm wrong) StaticBody3D and Rigidbody3D always needs to be the root of the scenes that make up my interactables and I cannot just swap those out - nor can I make them children of the interactable scene (at least I don't think so).

Right now I cannot really think of a few solutions:
1) Make ALL interactables Rigidbodies and have those that need to be static use the "Freeze" flag to turn them kinematic or static. That gives a lot more flexibility, but I am unsure if doing this will eventually result in a bottleneck that I am not yet aware of. In "other engine" I did go with this solution and it had the nice upside that moving such static/kinematic objects by player would provide basic collision with other Rigidbodies - which wasn't a necessity, but a nice bonus. But again, I am not sure if I will eventually run into performance issues using frozen Rigidbodies for potentially hundreds of objects that might as well be static objects. Does anyone have any insight in that?

2) Have two different interactable bases: interactable_static & interactable_dynamic which extend from StaticBody3D and RigidBody3D respectively. That would require some redundant scripting, but since some extra logic is required to handle these different scenarios anyway, that would not be THAT much of an issue.

3) Instead of relying on inheritance, using composition instead. I am pretty new to this concept and it SEEMS like it was made to solve problems like this, but considering I only have two distinctly different base types, it seems overkill.

I'd be insanely grateful for any help, feedback, other ideas - whatever you got. Thanks in advance! 🙂

  • d2clon replied to this.
  • 8Bit You can still write a common functionality class that inherits from PhysicsBody3D so it can be attached to both, rigid and static body nodes.

    8Bit StaticBody3D and Rigidbody3D always needs to be the root of the scenes

    I have not confirmed this but I think this assumption is not right, it will be very weird to me otherwise. You can have the root of your scene being a Node3D and attach different nodes to it as children, including StaticBody3D and others.

    • 8Bit replied to this.

      d2clon I think you're right about that. However I was thinking if Rigidbody isn't the root of the scene, but rather Node3D, that Node3D would stay in place while the Rigidbody child node moves around (I actually have to try that). I don't think there's a technical disadvantage with that, but it... looked wrong to me somehow.

        8Bit You can still write a common functionality class that inherits from PhysicsBody3D so it can be attached to both, rigid and static body nodes.

        • 8Bit replied to this.

          xyz Oh, I had no idea, but that makes so much sense! THANK YOU! 🙂

          8Bit that Node3D would stay in place while the Rigidbody child node moves around (I actually have to try that). I don't think there's a technical disadvantage with that, but it... looked wrong to me somehow.

          Yep, it was also a bit confusing for me at the beginning. Now I am used to it 🙂. The root Node3D marks the origin of the Scene you are building. Once you put this Scene into another Scene (Main/Game/Level/...), it becomes a subScene of that Scene, with origin in that root Node3D. This root Node3D will remain static (or not) will its children move around.

          • 8Bit replied to this.
            6 days later

            d2clon You know, I was at first very dismissive of your idea, because I wanted the "interactable" root where it actually was and reduce the amount of nodes wherever possible - especially since we talk about - potentially - having hundreds of those interactables in a level.
            But this Node3D root may actually be very handy. Since interactables can also snap to a grid or snap together at pre-defined joints while the player was dragging them around, I previously had to retain an "unsnapped transform" in form of position/rotation variables, so I would always know where the interactable would be if it wasn't snapped. And with a static root, this would be much easier as I could use an actual node for that - a marker OR another mesh - which could be like a "hologram" which would tell the player where the object ACTUALLY is and not just where it snapped to. I don't know if this makes sense without pictures/videos (I am bad at explaining this). So yeah this IS an interesting solution that even a week later I am still thinking about because once I start building all those interactables, I eventually have to commit since iterating 50 or more, even if they all inherit from a base scene, becomes a pain eventually.

              8Bit The sad news is that there is never only one good way of doing things. Everything has cons and pros. But this is the creative part of software development, isn't it? 🙂

              I would not try to implement the 50 versions of entities you need upfront. I would implement 2 or 3, put them in my game, and move to another area of the game and back and forth to see how one part interacts with the other. There are many chances that whatever version of your entity you end up with, even if after a lot of analysis, it will require changes at the end.

              • 8Bit replied to this.

                d2clon You're absolutely right of course. And that's how I'll start. Thing is - it's a rather simple sandbox game. And the code to interact with interactables - in a general way as well as their unique functionality of certain interactables - makes up about 75% of the code base and overall "work" of the entire project. In the Unity version I had already built around 80 of them - all inheriting from a simple base class. So the good thing is that I know where I need to be at. Now I just gotta make sure I use all possible advantages of Godot to reach that same goal and not "force the Unity solution" if that makes sense. 🙂