I'm trying to shoot shells from a tank. I've tried various shell types (KineticBody, RigidBody, Area) but I keep having troubles with placement and alignment, motion, gravity, and collisions.

On my tank model I have a spatial point (ShotStart) just past the end of my cannon barrel (child of the barrel) so that I can place a shell at the right spot. I instance the shell (a scene) and place it at ShotStart and align it with ShotStart so it's pointing in the right direction. Then I move it forward until it collides with something and I get the Node it collided with as well as the collisionshape within that node. Then I have the shell run StruckNode.TakeHit(player, collisionshape, damage)

I have various parts of that working depending on which type of node and the propulsion method. The most complete so far is KineticBody with move_and_collide() but I can't figure out how to apply gravity (not necessarily through physics). It seems to be the most straightforward way but I could easily be mistaken.

What is your favorite way of handling projectiles in 3d? Examples would be greatly appreciated too!

Yes I was looking at that before but looked much closer and did a bunch of experimenting. Turns out Area nodes ARE physics objects after all (I thought they were regular nodes). I also figured out I don't need to use apply_impulse() or anything, just set some things at the start then let it do it's own thing:

			bullet = Bullet.instance()
			add_child(bullet)
			bullet.transform = $Spawn.global_transform
			bullet.velocity = -bullet.transform.basis.z * bullet.muzzle_velocity

It flies off and I apply gravity inside the bullet itself with

	velocity += g * delta
	look_at(transform.origin + velocity.normalized(), Vector3.UP)
	transform.origin += velocity * delta

Then I hooked body_shape_entered() to its own script and did

func _on_Bullet_body_shape_entered(_body_rid, body, body_shape_index, local_shape_index):
	var armor = body.shape_owner_get_owner(body_shape_index)
	if body.name != "Ground":
		body.TakeHit(player, armor, Damage)
	queue_free()

Inside the body it hit I do this

func TakeHit(_from, _to, _damage):
	print(_from.name + " " + _to.name + " " + str(_damage))

So it's perfect. I set the player ID on the bullet then when it hits a collider "body" gives me the base node" and body_shape_index tells me which collider was hit. I'm really liking this now

Now I'm just working on shells slowing down due to air resistance. Pretty simple it seems. -C * Vsquare is the drag and I just subtract that from velocity.z

Ok well I got it working perfectly in an experimental project but once I moved the code into my main project it no longer works when it comes to placement.

In the experiment I use "bullet.transform = $Spawn.global_transform" to place the bullet at the correct place and orientations. In my actual project the bullet doesn't appear at the position I give

In the experiment $Spawn is a spatial and a direct child of the scene main node (spatial)
In the main program $ShotStart is a spatial and a child of VehicleBody->MeshInstance->MeshInstance-ShotStart (child of cannon which is child of turret which is child of vehicle)

As far as I know that should make no difference at all but I have to use "bullet.global_transform = ShotStart_global_transform" for the bullet to appear at the right place but then the angles are wrong (points 45 left and about 5 down instead of straight ahead in the direction ShotStart is pointing). Is this a bug or is there a different way I should be using when using a child spatial as the origin point?

Well I think I ran across an actual bug. I could place my shell in the right location and move it in the right direction. But if I didn't actually move it I could see the rotations were wrong. I checked all the node rotations and everything was a zeros yet it still showed up at a 45(ish). I deleted the shell scene and built a new one but that made no difference. Just now I moved the ShotStart to be a child of the main node and tried and the rotations were perfect. Then I made it a child of turret and again the rotations were perfect. Finally I tried it back as a child of cannon and suddenly it works perfectly again! This is with the only difference being that I changed the parent node then set it back. I changed no other settings at all.

So now placement is simple with "bullet.transform = shotstart.global_transform" Nothing else needed as the rotations are set by the parent's rotations etc. Moving forward uses the origin.z property and gravity uses Vector3.DOWN. Before the gravity worked but Z moved it to the left.

So that part is solved for me. I'm pretty sure it is a bug where some leftover setting was kept but not shown in the inspector which was only reset when I switched the Spatial node's parent,