You want to shoot projectiles from your player/mob/etc..
For this example, we’ll use the “Mini Tank” that we set up in KinematicBody: Movement.
Setting up the bullet
First, we’ll set up a “bullet” object that we can instance. Here are the nodes we’ll use:
Area: Bullet MeshInstance CollisionShape
For your mesh, you can use one of Godot’s built-in primitive shapes, or something like this:
If you’d like to use the bullet model pictured here, you can grab it from Kenney’s “Weapon Pack”.
Add your mesh to the
MeshInstance and a scale a collision shape to match.
Remember to align your
MeshInstance with the forward direction (-Z) of the
Area node, or your bullet won’t look like it’s flying the right way!
Add a script and connect the
extends Area signal exploded export var muzzle_velocity = 25 export var g = Vector3.DOWN * 20 var velocity = Vector3.ZERO func _physics_process(delta): velocity += g * delta look_at(transform.origin + velocity.normalized(), Vector3.UP) transform.origin += velocity * delta func _on_Shell_body_entered(body): emit_signal("exploded", transform.origin) queue_free()
We’re using a custom gravity vector,
g so that we can control how the shell flies from the tank’s cannon, giving it a nice arc effect. If you’d rather your projectiles move in a straight line, you can remove the line that applies it in
look_at() each frame turns the bullet to point in its direction of travel.
We’ll also emit an
exploded signal, which you can connect up to implement explosion and/or damage effects (but that’s for another recipe).
Now in the tank (or whatever object you have doing the shooting), add a
Position3D child at the point where you want the bullets to appear. In the case of our tank, we’re placing it at the end of the cannon barrel:
Now we can add the code to the tank’s script. First a way to add the bullet scene we’re going to instance:
export (PackedScene) var Bullet
_unhandled_input() (wherever you’re capturing input), add the code to instance the bullet:
if Input.is_action_just_pressed("shoot"): var b = Bullet.instance() owner.add_child(b) b.transform = $Cannon/Muzzle.global_transform b.velocity = -b.transform.basis.z * b.muzzle_velocity
That’s it - run your scene and try it out: