Godot - How to set up a modular character with collision being defined in the child nodes?

Viewed 633

I am triying to build "modular" ships in my 2d game, meaning a ship has a hull, an engine, cannons, etc. each being an own scene. A ship could be set up like this

Ship   
|- Hull  
  |- Sprite   
  |- CollisionShape
|- Engine  
  |- Sprite   
  |- CollisionShape
  |- ParticleSystem

Now I am stuck with the following problem. I set up the Ship node as KinematicBody2D as I use that node for movement. BUT the collision should come from the sub scenes (Hull, Engine, etc.). So I made them KinematicBodies too and added the CollisionShapes.

However this does not work, as the Ship needs a CollisionShape child (KinematicBody2D) and it being in the nested Scenes (Hull, Engine, etc.) does not suffice. In addition if I move the Ship node with move_and_collide/_slide the child nodes do not collide.

I do not think that my current approach is correct. What can I do to accomplish this without breaking my modularity by moving the children CollisionShapes to the Ship?

2 Answers

As a PhysicsBody2D, KinematicBody2D needs collision shape if you want it to collide with other physics bodies. So you could add a shape to the Ship node that will fit the entire ship or be slightly smaller than it.

Of course, there is more than one solution. A possible way suggests that you could make ship elements (engine, hull, cannons, etc) be the Area2D nodes. Using Area2D signals and _on_Area2D_area_entered(area) method you could code the unique response of events, like a collision with an enemy bullet, for each type of ship module.

Ship (KinematicBody2D)   
|
|__CollisionShape2D
|
|__Hull (Area2D)
|  |_Sprite   
|  |_CollisionShape2D
|
|__Engine (Area2D)  
   |_Sprite   
   |_CollisionShape2D
   |_ParticleSystem

I know this question is old, I had the same question until yesterday and found a solution, so here it is for anyone who still have this issue creating modular scenes:

In the Ship Kinematicbody create one CollisionShape for every ship module (you can add it through code if you wish) and through coding make each of the CollisionShapes you created for each module get the extents transforms (collisionshape.shape.extents.transform) from the CollisionShape present in the respectives module scenes (you will just use them to get the shapes you set, no need for the modules to be physics body as you only need the data from the collision extents).

Related