Help! Raycast3d Bullet Spawning not working correctly

Godot Version

4.3 Stable

Question

How to spawn bullet from barrel, I cannot get bullet to spawn from barrel of gun.
I have been following this video from LegionGames . The bullet spawner keep spawning bullet from the ground where player was first placed in Map.

I will paste codes from bullet.gd, player.gd.

This is player.gd

extends CharacterBody3D

#Signal
signal player_hit

#Constants
	#FOV variables
const BASE_FOV := 70.0
const CHANGE_FOV := 1.5
	#Movement Variables
const WALK_SPEED := 5.0
const SPRINT_SPEED := 8.0
const JUMP_VELOCITY := 4.5
const GRAVITY := 9.8
const SENSITIVITY := 0.01
	#head Bob variables
const BOB_FREQ := 0.05
const BOB_AMP := 0.05
	#hit stagger
const HIT_STAGGER := 8.0 


#Exports
@export var Player := get_parent()

#Variables
var SPEED
	#head Bob variables
var t_bob := 0.0
var direction: Vector3  
	#bullets
var bullet  = preload("res://Resources/Guns/bulllet.tscn")
var instance

#OnReady variables
@onready var Head := $Head
@onready var Camera := $Head/Camera3D
@onready var gun_anim := $Head/Camera3D/P90/AnimationPlayer
@onready var gun_barrel := $Head/Camera3D/P90
 
 

func _ready() :
	Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
	#for child in $WorldModel.find_children("*", "VisualInstance3d"): 
		#child.set_layer_mask_value(1, false) 
		#child.set_layer_mask_value(2, true)
		
func _unhandled_input(event):
	if event is InputEventMouseMotion:
		Head.rotate_y(-event.relative.x * SENSITIVITY)
		Camera.rotate_x(-event.relative.y * SENSITIVITY) 
		Camera.rotation.x = clamp(Camera.rotation.x, deg_to_rad(-40), deg_to_rad(60))
			
			
func _physics_process(delta: float) -> void:
	# Add the gravity.
	if not is_on_floor():
		velocity += get_gravity() * delta

	# Handle jump.
	if Input.is_action_just_pressed("Jump") and is_on_floor():
		velocity.y = JUMP_VELOCITY

	# Handle Sprint
	if Input.is_action_pressed("Sprint"):
		SPEED = SPRINT_SPEED
	else :
		SPEED = WALK_SPEED

	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	
	var input_dir := Input.get_vector("StrafeLeft", "StrafeRight", "Forward", "Backward")
	var direction:Vector3 = (Head.transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
	if is_on_floor():
		if direction:
			velocity.x = direction.x * SPEED
			velocity.z = direction.z * SPEED
		else:
			#velocity.x = move_toward(velocity.x, 0, SPEED)
			velocity.x = lerp(velocity.x, velocity.x * SPEED, delta * -3.50)
			#velocity.z = move_toward(velocity.z, 0, SPEED)
			velocity.z = lerp(velocity.z, velocity.z * SPEED, delta * -3.50)
	else:
		velocity.x = lerp(velocity.x, velocity.x * SPEED, delta * 0.01)
		velocity.z = lerp(velocity.z, velocity.z * SPEED, delta * 0.01)
			
	#Head_BOB Phy
	t_bob += velocity.length() * float(is_on_floor())
	Camera.transform.origin = _HeadBOB(t_bob)

	#FOV
	var velocity_clamped = clamp(velocity.length(), 0.5, SPRINT_SPEED * 2)
	var target_fov = BASE_FOV + CHANGE_FOV * velocity_clamped
	Camera.fov = lerp(Camera.fov, target_fov, delta * 4 )
	
	***#Shooting***
***	# Shooting***
***	if Input.is_action_pressed("Shoot"):***
***		if !gun_anim.is_playing():***
***			gun_anim.play("P90Armature|Fire")***
***			instance = bullet.instantiate()  # Use instantiate() for Godot 4.x***
***			instance.global_transform = gun_barrel.global_transform ***
***			instance.global_transform.basis = gun_barrel.global_transform.basis***
***			get_tree().root.add_child(instance)  # Add instance as a child to the parent node***

	
	move_and_slide()

func _HeadBOB(time) -> Vector3:
	var pos = Vector3.ZERO
	pos.y = sin(time * BOB_FREQ) * BOB_AMP
	pos.x = cos(time * BOB_FREQ/2) * BOB_AMP
	return pos

func _hit(dir):
	emit_signal("player_hit")
	velocity += dir * HIT_STAGGER

this is bullet.gd

extends Node3D
#signals
#consttants
const SPEED := 40.0

#exports
#var
#onready
@onready var mesh := $MeshInstance3D
@onready var ray := $RayCast3D

# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	pass # Replace with function body.


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta) -> void:
	position += transform.basis * Vector3(0, 0, -SPEED) * delta



Simple fix, add the bullet to the tree before you apply the transform.

	if Input.is_action_pressed("Shoot"):
		if !gun_anim.is_playing():
			gun_anim.play("P90Armature|Fire")
			instance = bullet.instantiate()  # Use instantiate() for Godot 4.x
			get_tree().root.add_child(instance)  # Add instance as a child to the parent node
			instance.global_transform = gun_barrel.global_transform 
			instance.global_transform.basis = gun_barrel.global_transform.basis

Thanks @wchc , It worked like a charm :star_struck:

1 Like

Great! Make sure to mark my answer as a solution, so that other users know it has been resolve in case they ever encounter a similar problem.

1 Like

yes @wchc , but a little help is needed, as the bullet spawns from the player mesh.
As the RayCast3d is attached to the barrel of the gun, which you can see in the picture above. I tried moving raycast here and there in the editor menu, but it doesn’t spawns from the barrel of the gun. :sweat_smile:

You assign your gun_barrel to the P90 node, so moving only this node (or any of its ancestors) would affect your spawning position. If you want your spawning position to be the RayCast3D node, then assign it to your gun_barrel.

@onready var gun_barrel := $Head/Camera3D/P90/RayCast3D

Edit: on a side note, I think you don’t need this line. You already assigned a full global_transform in the previous line, which includes the basis, no need to assign it again.

instance.global_transform.basis = gun_barrel.global_transform.basis
1 Like


adding the above line only generated an error, tried changing

get_tree().Head.get_child(instantiate)

but it also generated error

Ah sorry, its further down the tree, I didn’t notice you have 2 nodes named P90.

@onready var gun_barrel := $Head/Camera3D/P90/P90Armature/Skeleton3D/P90/RayCast3D
1 Like

@wchc I solved it with your block of code and little bit rearrangement of RayCast3d. :face_holding_back_tears:
Which resulted in my bullet colliding mid air and triggering the Spark particles.

1 Like