GMLscripts.com

Discuss and collaborate on GML scripts
Invert

You are not logged in.

#1 2009-07-04 11:59:11

flexaplex
Member
Registered: 2008-12-11
Posts: 72

instance_activate/deactivate_* - bug when executing both in draw event

Brief Description:            instance_activate/deactivate_* - can cause a bug when deactivating and reactivating an instance in the same draw event under certain conditions
GM Versions:                   GM6, GM7
References:                     [1]
Example File:                   Deactivation in draw event.gmk
Bug Confirmed:                Yes
Hardware Dependent:     No

Main Info:

This bug occurs when you deactivate and then reactivate an instance within the same draw event, the bug however only happens under very specific conditions. I advise looking at the example (Deactivation in draw event.gmk) to see the bug more clearly.

- Scenario

The following is a scenario that gives rise to the bug. I am unsure of all the other scenarios which makes it occur.

Make 3 objects (object0,object1,object2) and place them in a room in that order. Give object0 and obect1 a depth of -1 and object2 a depth 0.

Then place this code in the draw event code of object0:

Expandinstance_deactivate_object(object2);
instance_activate_object(object2);

- Outcome

The outcome of doing this is that the bug makes object1's draw event be skipped (you can see it is not drawn). If you look closely at the example file you should also notice that the text drawn by object2 is darker when the error is occurring (it looks about the same darkness as if the text were to be drawn 2 times on the same spot) and is the same colour as the other 2 if you change the file so the bug is not occurring. This is because the bug is also making the draw event of object2 be executed twice.

- Further tests

After doing some more tests I found these results.

The bug does not occur unless the depths of BOTH object0 and object1 are set lower than object2 and object1 has a depth equal to or lower than object0
The bug does not occur when you place the objects in the room in a different order (from what I tested of the orders)
The bug does not occur for object0 if you place the code in object1's draw event

The bug does not occur if you change the draw event code to:

Expandinstance_deactivate_object(object2);
instance_activate_object(object2);
instance_deactivate_object(object1);
instance_activate_object(object1);

But DOES occur if you change the draw code to:

Expandinstance_deactivate_object(object1);
instance_activate_object(object1);
instance_deactivate_object(object2);
instance_activate_object(object2);

If you use:

Expandif (check)
{
  instance_deactivate_object(object2);
  instance_activate_object(object2);
}

object1 is only deactivated while check is true and is reactivated somehow when it is not.

From these further tests and logical conclusion it appears that deactivating and reactivating under these certain conditions is messing with GM's internal drawing list. What I believe is happening is when you use:

Expandinstance_deactivate_object(object2);

In this particular set-up it is wrongly taking object1 out of the drawing queue instead of object2, then when you use:

Expandinstance_activate_object(object2);

It is putting an extra draw in the queue for object2.

Then if you just use:

Expandinstance_deactivate_object(object1);

The instance deactivate for object1 must be indexed with the wrongly assigned extra draw of object2 because putting this on it's own sets the draw event of object2 back to occurring 1 time a step but leaves object1's draw event being skipped. Then if you also use:

Expandinstance_activate_object(object1)

It now puts the draw event of the normal object1 back into the queue.

Game Maker must also reset the drawing queue every step otherwise it wouldn't just get reset back to it's correct order on it's own when the bug is not occurring.  I think the underlying cause of this bug is likely to be the same bug found in the other deactivation bug topic: http://www.gmlscripts.com/forums/viewtopic.php?id=1627

Workaround:

Avoid deactivating and reactivating instances in the same draw event. A common reason for wanting to do this is for cycling through instances for collision checking functions, instead though you can alternatively be done by moving the instances out of the room then back in.

Last edited by flexaplex (2009-09-04 12:39:52)

Offline

#2 2010-08-15 00:11:22

icuurd12b42
Member
Registered: 2008-12-11
Posts: 303

Re: instance_activate/deactivate_* - bug when executing both in draw event

Here is another.

If you deactivate within a with clause and other instances also deactivate withing a with clause in the same even, alarm in this case. the system fails


Information about object: object0

Sprite: <no sprite>
Solid: false
Visible: true
Depth: 0
Persistent: false
Parent: <no parent>
Mask: <same as sprite>

Create Event:
execute code:

alarm[0] = 1;

Alarm Event for alarm 0:
execute code:

var ct; ct = 0
show_debug_message("alarm for " + string (id))
with(all)
{
show_debug_message(string(other.id) + " sees " + string (id))
if(id == 100001 and id <> other.id)
{
show_debug_message(string(other.id) + " deactivates " + string (id))
instance_deactivate_object(id);
}
ct+=1;
}

show_debug_message("--------------------")

______________________________

It's not really obvious what goes on in there but you clearly see the list get corrupted. Drop 4 in the room a run debug.

instance 100002 will deactivate instance 100001

Result, GM7

Expandalarm for 100001

100001 sees 100001

100001 sees 100002

100001 sees 100003

100001 sees 100004

-------------------- << as expected

alarm for 100002

100002 sees 100001

100002 deactivates 100001
<<Missing 100002 sees 100002
100002 sees 100003

100002 sees 100004

<< and drops into the code for instance 3, missing --------------
alarm for 100003

100003 sees 100002

100003 sees 100003

100003 sees 100004

--------------------

alarm for 100004

100004 sees 100002

100004 sees 100003

100004 sees 100004

--------------------

I was chasing a bug. I have controllers that look what's underneath them and disables it to re-enable later. it all started to go hay wire. It was really odd. I would remove an unrelated instance and it would suddenly work..  anyway, to bypass, I differed the deactivation in an alarm, once all were done with the with(all), I would store the instances in a ds list and run an alarm to perform the deactivation on the next step.

Last edited by icuurd12b42 (2010-08-15 00:13:27)

Offline

Board footer

Powered by FluxBB