Bug or wrong code? local vs self (SOLVED)

Hello! :wave:

II’ve been creating some AI prototypes, and I’m at the stage of the damage system where I’ve had a problem.

AI:
health = 10

damage:
health – 2

if health <= 0 delete.

It’s the most common formula and it works, however by duplicate the AI they get corrupted!.
(Not only in the function of damage, but also with other adepts). :sob:

Why? :thinking:

This applies in 2D and 3D. (The duplicate is copied and pasted into the same collection or across the instance with the factories.)


Show us the code :smiley: enemy.script

1 Like

It’s a very basic code! :wink:

local health

function init(self)
	health = 10
	label.set_text("#label", "health ".. health)
end

local function damage(self, value)
	health = health - value
	label.set_text("#label", "health ".. health)
	pprint("health", health)
	if health <= 0 then
		health = 0
		go.delete()
	end
end

function on_message(self, message_id, message, sender)
	if message_id == hash("damage") then
		damage(self, message.damage)
	end
end
1 Like

Ok, so the quick answer is:

Change local health to self.health and initialize it in init(). Meanwhile I will write an explanation why.

-- remove this line: local health

function init(self)
	self.health = 10 -- change to self.health
	label.set_text("#label", "health ".. self.health) -- and all health to self.health
end
1 Like

Understanding root cause:

You define local variable health. It’s simply same for all script instances. If you modify it for one enemy it is modified for the others. self is on the other hand unique for all instances. Read more:

Explanation of behavior visible in the video:

But how to exaplain the behavior from the video?
You can say “it would then be that the enemy behind should update the health too each time?”

No, because you are calling damage only in on_message and it looks like you are sending the message to the correct game object correctly. So that only first object receives a message “damage” and it sets a new health value in label, so you see it only on the first enemy.

But, as explained above, you are modifying health for all instances, so that when the first enemy is deleted correctly after health < 0, you have a situation you are shooting the second enemy and it gets message damage, so calls damage function, but health is already < 0!

So it instantly sets label to updated health value (health - value, probably -2) and because it’s <= 0 removes instantly the second enemy :wink:

Advices:

  • Read the chapter on scoping from the link above :wink:
  • Use extensively print() if in trouble
  • or use Defold debugging (which would be soo cool in such a case, put a breakpoint in the beginning of damage function and see what health values you have, when the second enemy is killed)

:wink:

Let us know if it solves the issue and if you need any help :smiley: (jeez, sounds like AI xD)

4 Likes

This works! :+1:

I appreciate your help! :blush:
Thank you.

1 Like