Godot Version
Godot 4.4.1 stable
Question
Strap in.
Trying to spawn a projectile from the player facing and an offset position based on that facing. This all works EXCEPT the projectile position appears at 0,0 in my level. It flies fine, it’s direction is set correctly, it disappear at the end of it’s range.
It’s a bit convoluted as this is being triggered by a “use_item” action off my player action script. I have four 2d markers in my player tree for determining offset to instantiate weapons, tools and other effects (four direction game, basically a zelda-like) based on facing. It tells the inventory to use the item.
func use_item() -> void:
is_iteming = true
var item = equipped_items.front()
if item != null:
var item_pos: Vector2
if last_direction == Vector2.UP:
item_pos = marker_up.position
elif last_direction == Vector2.RIGHT:
item_pos = marker_right.position
elif last_direction == Vector2.LEFT:
item_pos = marker_left.position
elif last_direction == Vector2.DOWN:
item_pos = marker_down.position
#this is the line that leads to the next script
PlayerInventory.use_item_action(item, last_direction, item_pos)
play_animation("interact", last_direction)
await animated_sprite_2d.animation_finished
else:
is_iteming = false
return
is_iteming = false
To PlayerInventory Global:
In the inventory global script, the inventory determines what kind of item it is (world affecting or player affecting). If it’s “world effecting” it takes the player facing and the offset position and passes them to the loaded script through the execute function. if the execute was completed it returns true and it removes one item from the stack.
func use_item_action(item, facing, position):
var effect = load(item["source"])
if item["use_type"] == 0:
#this is the line that leads to the next script
var used = effect.item_execute_effect(player_node, facing, position)
if used:
# remove one quantity of item
PlayerInventory.remove_item(item)
PlayerInventory.remove_equip_item(item)
else:
pass
In the effect execute script, this is a ‘thrown item’, like a shuriken or axe. The projectile scene is an export on the specific resource so I can use one instantiation script for multiple types of items. The shot scene is instantiated, and then I parent it to my current scene (the level loaded, I print it immediately and it is showing up as my level). I then trigger the projectile script to ‘fire’.
@export var shot: PackedScene
#player variable is inherited from ItemEffect parent but I'm not using it in this script
func item_execute_effect(p, dir, pos):
print("item executed")
player = p
var thrown = shot.instantiate()
Engine.get_main_loop().current_scene.get_tree().get_first_node_in_group("ActiveRealm").add_child(thrown)
print(thrown.get_parent())
#this is the line that leads to the next script
thrown.fire_shot(dir, pos)
Projectile scene Script:
I set the direction and global_position based on the variable I passed in, and then free it to begin movement until it reaches the end of it’s range:
func fire_shot(shoot_dir, pos):
print("axe shot")
direction = shoot_dir
global_position = pos
start_pos = pos
can_fly = true
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
if can_fly:
global_position += direction * speed * delta
if global_position.distance_to(start_pos) > shot_range:
queue_free()
pass
What’s weird is all of the script for instantiating the weapon and the projectile is lifted from a ranged weapon I have that works perfectly, the only difference being that the weapon is already part of the tree so parenting it to the scene is less complicated: get_tree().get_first_node_in_group("ActiveRealm").add_child(instance)
What am I missing?
