Trouble with transform in area2d projectile

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Rensae

Hi ! I’m actually having troubles figuring out an issue I have with a skill that can be a melee aoe around the player, or a projectile if a condition’s true.

It goes well for first enemy, but when it’s focusing a second one, it derps and seems to go in the opposite y axis ? Not very good with vectors yet.

Here are the codes used in this portion :

func _loading_skills(selected_skill):
_get_closest_enemy()
match character:
	"Shade" :
		match selected_skill :
			"Reap":
				if min_enemy != null:
					if reap_cd == false:
						reap_cd = true
						is_attacking = true
						var reap_instance = reap_scene.instance()
						reap_instance.damage = atk
						if boosted == true:
							reap_instance.damage = atk*2
							reap_instance.pen = true
							reap_instance.transform = $Muzzle.global_transform
							reap_instance.projectile = true
						reap_instance.position = position
						reap_instance.hit_radius = PlayerData.character_skills_data["Shade"]["Reap"]["radius"]
						stamina -= PlayerData.character_skills_data["Shade"]["Reap"]["cost"]
						owner.add_child(reap_instance)
						yield(get_tree().create_timer(PlayerData.character_skills_data["Shade"]["Reap"]["cooldown"]), "timeout")
						reap_cd = false
						is_attacking = false

This one’s for launching the function getting the closest enemy as well as setting up and instancing the skill.

func _get_closest_enemy():
var min_dist = 99999
var enemies = get_tree().get_nodes_in_group("enemies")
for enemy in enemies:
	var dist = pos.position.distance_to(enemy.position)
	if (dist < min_dist):
		min_dist = dist
		min_enemy = enemy
	if enemy != null:
		$Muzzle.look_at(min_enemy.position)
if enemies.empty():
	min_enemy = null
return min_enemy

This one returns the closest enemy to the function that called it.

var damage
var hit_radius
var projectile = false
var speed = 250
var damaged = []
var pen = false


func _ready():
	_Animation()
	$CollisionShape2D.shape.radius = hit_radius 

func _process(delta):
	if projectile == true:
		position += transform.y * speed * delta

func _Animation():
	get_node("AnimationPlayer").play("Reap")
	yield(get_tree().create_timer(1.95), "timeout")
	queue_free()


func _on_Reap_body_entered(body):
	if body.is_in_group("enemies") and !damaged.has(body):
		body._on_hit(damage)
		#body.append(damaged)
		if pen == false:
			queue_free()

And this one is the script on the skill.

I can’t figure out how to fix this issue, so I’d take any help and tips you guys could give me.

Here’s an additional video is it helps understand how the projectile is acting : https://youtu.be/ttm3h8KfoF8

Not sure if it’s related to the problem or not, but…

  • You say that _get_closest_enemy() returns the closest enemy to the caller, and it does but…
  • When you call _get_closest_enemy(), you don’t actually store (or use) that return value
  • That implies that min_enemy is a global variable of some sort. You don’t show where it’s created.

Are you potentially modifying the global min_enemy variable elsewhere?

Also, you don’t show where a dead enemy is queue_free()'d. Is the enemies collection accurate (as expected) each time you call _get_closest_enemy()?

jgodfrey | 2022-05-12 14:24

Oh sorry, guess I forgot that…

min_enemy is a variable stored in the player script running the _loading_skills function ! So yeah, it’s a global one.

#Detection stats
    var min_enemy
    var character

For the enemy, I’m using a script on a healthbar which gets inherited by each enemy and player, since I havea kind of zelda heart thingy. Here’s where the objects get queue_freed on death :

var bar = get_tree().get_nodes_in_group("health " + get_parent().name).size() - damage
	if bar <= 0:
		if parent.is_in_group("enemies"):
			parent._achievement_count()
		parent.queue_free()

I could give the whole code, but it’s pretty long…

For explaining, it actually counts how much object there’s in the container after the damage, and if there’s none left, it queue_free the parent.

I’m also not changing the min_enemy elsewhere than the function _get_closest_enemy(), and it’s only used to get the Muzzle to look at the enemy, and I then take the global_transform of the Muzzle and apply it’s transformation to the children

I also tried to print each body and which one was the closest, and it indeed seemed to work as intended

Rensae | 2022-05-12 14:32