High Level Plan

Apply an impulse to a RigidBody. When the body has travelled far enough (or if enough time has passed), delete it.

Scene Tree

Create a new scene, call it GodotBullet. Here is what the node tree should look like for this scene:

  • RigidBody2D
    • CollisionShape2D
    • Sprite

Scripting

Attach a script to the RigidBody2D node of the GodotBullet scene. Call the script GodotBullet.cs.

Create a few public fields in your GodotBullet class to allow clients to customize certain aspects of the bullet:

// File: GodotBullet.cs

public class GodotBullet: RigidBody2D{
    // Public Fields
    public float MaxDistance = 800; // How far (in pixels) the bullet will travel before it is destroyed
    public float MaxSeconds = 1;    // How long (in seconds) before the bullet is destroyed
    public float ImpulseMag = 1200; // How much impulse to give the bullet when it is launched
}

Create a private field that will allow us to track how far the bullet has travelled (so that we can destroy it when it has travelled far enough):

// File: GodotBullet.cs

public class GodotBullet: RigidBody2D{
    // ...
    private Vector2D origianlPos;
    // ...
}

Create a LaunchBullet method, which the client can call to…well…launch the bullet (the bullet will be stationary until this method is called):

// File: GodotBullet.cs

public class GodotBullet: RigidBody2D{
    // ...
    public void LaunchBullet(){
        this.originalPos = this.Position; // save the position the bullet was launched from

        // start a timer that will delete the bullet when it has lived long enough
        Timer timer = new Timer();
        timer.WaitTime = this.MaxSeconds;
        timer.OneShot = true;
        timer.connect("timeout",this,nameof(OnTimeToDie));
        timer.Start();

        this.ApplyCentralImpulse(this.Transform.x.Normalized() * this.ImpulseMag); // apply an impulse in the same direction that the bullet is facing
    }
    // ...
}

Implement the OnTimeToDie method:

// File: GodotBullet.cs

public class GodotBullet: RigidBody2D{
    // ...
    private void OnTimeToDie(){
        this.QueueFree();
    }
    // ...
}

Every physics frame, we need to check if the bullet has travelled far enough, if so, we delete it. Thus, we need to implement physics frame for this class:

// File: GodotBullet.cs

public class GodotBullet: RigidBody2D{
    // ...
    public override void _PhysicsProcess(float delta){
        float distanceTravelled = this.Position.DistanceTo(this.originalPos);
        if (distanceTravelled > this.MaxDistance)
            this.QueueFree();
    }
    // ...
}

How to Use the Bullet

The client can use the bullet by instancing the GodotBullet scene, positioning/orienting the bullet however they want, and then calling its LaunchBullet() method.

PackedScene bulletScene = GD.Load<PackedScene>("res://GodotBullet.tscn");

GodotBullet bullet = (GodotBullet)bulletScene.Instance();
bullet.Position = new Vector2D(200,200);
bullet.Rotation = Mathf.Deg2Rad(40);

bullet.LaunchBullet();

The Final Product

Click anywhere to spawn a bullet.