While learning about the Godot engine, I am trying to write a simple spaceships game.
A spaceship, as I have found out, can be defined as a scene of its own, with the following internal structure:
RigidBody2D // the root of the scene
|- Sprite2D // the image representing the spaceship
|- CollisionPolygon2D // the collision shape
Now, I can add this "Spaceship" scene into my main game scene, which then looks like this:
Node2D
|- Spaceship // instance of the above scene
|- RemoteTransform2D // makes the camera follow the ship
In here, I have attached a C# script on the Spaceship node that does a simple check for input and calls methods like AddConstantCentralForce
and AddConstantTorque
n its _Process
method to move the ship according to player input:
Node2D
|- Spaceship + InputControl.cs
|- RemoteTransform2D
So far, this works fine.
Problem: I also need (?) to attach a script to the root node of my Spaceship scene. That is because I want to dynamically add some additional nodes in there, depending on what is happening in the game, and I think the root object of the scene would be the appropriate place to handle this logic:
RigidBody2D + ManageShip.cs
|- Sprite2D
|- CollisionPolygon2D
But if I do this, it has no effect - the script on the root node of the Spaceship scene is replaced by the script on the Spaceship node in my main scene.
Possible alternatives:
- I do not want to integrate the input control script into the Spaceship scene, because only the player ship should be controlled like this, whereas I want to reuse the Spaceship scene also for enemy ships.
- I have tried to wrap the Spaceship node in a
Node2D
node in my main scene, but then I cannot attach my input control script becauseNode2D
does not have the methods likeAddConstantCentralForce
:Node2D |- Node2D + InputControl.cs |- Spaceship |- RemoteTransform2D
- I have tried to wrap the Spaceship node in a
RigidBody2D
node instead, but then, my input seems to have no effect because thatRigidBody2D
itself has no mass and/or shape (as is also pointed out by the Godot IDE with a warning symbol):Node2D |- RigidBody2D + InputControl.cs |- Spaceship |- RemoteTransform2D
What node type should I use instead? Is there a scene design guideline by Godot for this?
Is the solution maybe to wrap Spaceship in just a Node2D
and rewrite the input control script to find the nested RigidBody2D
and call the methods on that instance?
But then, it seems that it would be my Spaceship scene flying around in this wrapping node rather than in the global space. That doesn't seem right. Or, looking at it differently, that would mean I could just as well handle input in a script on the main scene's root node (or anywhere else in the scene) and just notify the player object about the input. This will work, but is it the intended way to use Godot?
To elaborate on the workaround I suggested in the end, I have now implemented it like this:
Right below my main scene root, I have added a Node2D
and attached InputControl.cs
to it. On that node, I have added a metadata value named PlayerNode
of type NodePath
and assigned my Spaceship node from the same scene to it.
Node2D
|- Spaceship + (whatever script is attached in the scene)
|- RemoteTransform2D
|- Node2D + InputControl.cs
The InputControl
class now inherits from Node2D
and has a Player
property of type RigidBody2D
that is used as the target of my calls to ship movement methods. I initialize the object as follows:
public override void _Ready()
{
var player = GetNode(GetMeta("PlayerNode").AsNodePath()) as RigidBody2D;
if (player == null)
{
throw new InvalidOperationException("Player object not found.");
}
Player = player;
}
This works, is easy to implement (once you know what API methods to use) and it's easy to understand, still - being a total beginner in Godot - I wonder whether this is the way we're supposed to use Godot?