GMS 2 collision_rectangle_list leads to crash with certain objects

Lunnig149

Member
I am currently (=quite some while) struggling with the following piece of code and just can not put my finger onto what is going wrong. Any kind of hint or idea is highly appreciated.
(I am afraid it is something obvious and I am about the embarrass myself xD)

Problem Description:
version_1: works for a while (times differ from run to run), but after the collision with certain objects the game simply crashes (game works perfectly fine without this section of code).
version_2: works fine
version_3: works fine

versions only differ in the collision_rectangle_list and only in the object checked for)

Code:
//// Healing if a object with hp moves into it
/*version_1*/            var _num_list    = collision_rectangle_list(bbox_left , bbox_top , bbox_right , bbox_bottom , all        , false , false , list_collision , false);
/*version_2*/            var _num_list    = collision_rectangle_list(bbox_left , bbox_top , bbox_right , bbox_bottom , oCharacter , false , false , list_collision , false);
/*version_3*/            var _num_list    = collision_rectangle_list(bbox_left , bbox_top , bbox_right , bbox_bottom , id_creator , false , false , list_collision , false);
                    if (_num_list > 0) {    
                        for (var i = 0 ; i < _num_list ; i++) {
                                var _inst_checked = list_collision[| i];
                            if (instance_exists(_inst_checked)) {
                                with (_inst_checked) {  
                                            /// some actions removed for debugging
                                            /// error still happening with out this section
                                    }
                                }
                            }
                        }
                    }
        
                        ds_list_clear(list_collision);
 

Lunnig149

Member
Well this line is unnecessary, so existence is not the problem.
True, the instance checking is not needed since its existence is checked for by the collision. Thank you for that :) .


Check the size of the list each time.
Just to be sure do you mean something else than checking the the list is filled at all?
Am I not doing that by checking that with the following condition:
Code:
if (_num_list > 0) { ... }
When you say simply crashes, do you mean it freezes, throws up an error message, or just plain shuts down automatically?
It just shuts down automatically.

Output:

X://windows/Runner.exe exited with non-zero status (-1073741819)
elapsed time 00:00:13.0178706s for command "C:\ProgramData/GameMakerStudio2/Cache/runtimes\runtime-2.2.5.378/bin/Igor.exe" -j=8 -options="C:\Users\Chris\AppData\Local\GameMakerStudio2\GMS2TEMP\build.bff" -v -- Windows Run started at 06/29/2020 12:53:12
"cmd" /c subst Z: /d

elapsed time 00:00:00.0899713s for command "cmd" /c subst Z: /d started at 06/29/2020 12:53:25
"cmd" /c subst Y: /d

elapsed time 00:00:00.0879720s for command "cmd" /c subst Y: /d started at 06/29/2020 12:53:25
"cmd" /c subst X: /d

elapsed time 00:00:00.0929702s for command "cmd" /c subst X: /d started at 06/29/2020 12:53:25
FAILED: Run Program Complete
For the details of why this build failed, please review the whole log above and also see your Compile Errors window.


Compile Errors:

There are no compile errors to show!
 

TailBit

Member
Does it happen if you remove the with() part too?

And instead do the instance changes by variables using the id from _inst_checked:
GML:
_inst_checked.hp += 10;
 

Lunnig149

Member
Does it happen if you remove the with() part too?

And instead do the instance changes by variables using the id from _inst_checked:
GML:
_inst_checked.hp += 10;
Checked it right now. Happening, too.


Addition: (should not be a problem, but better to be safe than sorry):
The only other section of code in the object (its above the one posted) is the following

GML:
 /// following the creator if it exists and condition on is fulfilled
            if (follow_creator == true) {
                if (instance_exists(id_creator)) {    
                    x = id_creator.x;
                    y = id_creator.y;
                }
            }
 

Nidoking

Member
What makes you so sure that every instance that collides has follow_creator and id_creator defined? That's probably why it fails when you use all - you're colliding with things that don't have those variables, and the program is crashing when it tries to reference those variables.
 

TailBit

Member
@Nidoking the opening post states that it fails even without that part
GML:
/// error still happening with out this section
So I wonder how many of the inner checks that can be removed before it is stable..

You could also put show_debug_message 's along the way. Maybe it can display the _num_list before it happens
 

Lunnig149

Member
Maybe I should clarify (sorry for the confusion)
That is the whole code (removed instance_exists as suggested, since not needed):

Code:
//// Healing if a object with hp moves into it
/*version_1*/            var _num_list    = collision_rectangle_list(bbox_left , bbox_top , bbox_right , bbox_bottom , all        , false , false , list_collision , false);
/*version_2*/            var _num_list    = collision_rectangle_list(bbox_left , bbox_top , bbox_right , bbox_bottom , oCharacter , false , false , list_collision , false);
/*version_3*/            var _num_list    = collision_rectangle_list(bbox_left , bbox_top , bbox_right , bbox_bottom , id_creator , false , false , list_collision , false);
            if (_num_list > 0) {    
                for (var i = 0 ; i < _num_list ; i++) {
                    var _inst_checked = list_collision[| i];
                    with (_inst_checked) {  
                        /// some actions removed for debugging
                        /// error still happening with out this section
                    }
                }
            }
        
                        ds_list_clear(list_collision);

 /// following the creator if it exists and condition on is fulfilled
            if (follow_creator == true) {
                if (instance_exists(id_creator)) {    
                    x = id_creator.x;
                    y = id_creator.y;
                }
            }
The variables: "id_creator" and "follow_creator" are created with the create event of the object in question.
 

TheouAegis

Member
He'd be getting an error message with that anyway, unless they got rid of error messages. Crashing is usually a stack overflow or memory error.

How many objects do you have?

And when I say check the size of the list, I just made I'm curious how big that list is getting. Also if you put a debug message or show_message() right after the list is populated - before you loop through the list - and the game crashes without that message showing up, then the issue is with the list being populated itself, which would suggest a memory error. If the message pops up and then the game closes, then... That's weird.

I don't know if it's an option, but go into your game settings as well as your program settings and make sure error messages are not disabled. It was an option in older versions of game maker, make sure you didn't accidentally disabled error messages in your version, if it's still an option.
 

Lunnig149

Member
How many objects do you have?
The list is populated with something between 2 to 13 objects. Most of the time its around 3-4 objects. The game also handles the object quite well for about 2 to 30 seconds before the crash.

I don't know if it's an option, but go into your game settings as well as your program settings and make sure error messages are not disabled. It was an option in older versions of game maker, make sure you didn't accidentally disabled error messages in your version, if it's still an option.
Showing errors is enabled. No message is shown in this case. (I cause an error on purpose and that worked just fine.)
 

Lunnig149

Member
As always I am really grateful for any kind of help and/or hint :).

Additional discoveries regarding this problem:

Changing the "collision_rectangle_list()" function to the following functions leads to different results (see comment after each function on what WORKS and DOES NOT WORK).

Code:
//// Healing if a object with hp moves into it
/*version_1 */    var _num_list    = collision_rectangle_list(    bbox_left , bbox_top , bbox_right , bbox_bottom , all            , false , false , list_collision , false); //    DOES NOT WORK   
/*version_1a*/    var _num_list    = collision_circle_list(    x , y , 300                                       , all            , false , false , list_collision , false); //    WORKS  /// COMMENT: radius range does not matter        
/*version_1b*/    var _num_list    = collision_ellipse_list(    bbox_left , bbox_top , bbox_right , bbox_bottom , all            , false , false , list_collision , false); //    WORKS           
/*version_1c*/    var _num_list    = collision_line_list(        bbox_left , bbox_top , bbox_right , bbox_bottom , all            , false , false , list_collision , false); //    DOES NOT WORK
/*version_1d*/    var _num_list    = collision_point_list(        x , y                                            , all            , false , false , list_collision , false); //    WORKS           
/*version_2 */    var _num_list    = collision_rectangle_list(    bbox_left , bbox_top , bbox_right , bbox_bottom , oCharacter    , false , false , list_collision , false); //    WORKS           
/*version_3 */    var _num_list    = collision_rectangle_list(    bbox_left , bbox_top , bbox_right , bbox_bottom , id_creator    , false , false , list_collision , false); //    WORKS           
                    if (_num_list > 0) {   
                        for (var i = 0 ; i < _num_list ; i++) {
                                var _inst_checked = list_collision[| i];
                            with (_inst_checked) {
                                if (variable_instance_exists(id , "hp")) && (variable_instance_exists(id , "hp_max")) {
                                        if (hp <hp_max) {   
                                                 /// some actions removed for debugging
                                                 /// error still happening with out this section
                                        }
                                }
                            }
                        }
                    }
       
                        ds_list_clear(list_collision);
Does that help?
Any opinions on the issue?
Any hints on what to check next to get to the bottom of it?
 

TheouAegis

Member
I would debug objects.
Code:
var i=0, num_list = 0;
while 1 {
    if !object_exists(i) break;
    show_debug_message(i);
    _num_list    += collision_rectangle_list(    bbox_left , bbox_top , bbox_right , bbox_bottom , i    , false , false , list_collision , false);
}
When it crashes,see what the last number in the output window is. If it is the highest number, the crash is outside the loop OR the last object in your resource tree. If that is the case, move that object up a slot in the resource tree and run the test again. If the crash value also goes down, it's that object. BUT if the crash value is not the highest number, write it down. Run the test again and compare the next crash number. If it is the same, that object is the culprit. If it is different, back to square one.
 

Lunnig149

Member
Good Idea, I'll look into it with this method to figure out what step is causing the error. (I'll update as soon as I know more.)
 

Nidoking

Member
What if you create a new list and destroy it each time, instead of using the same list? Reusing lists this way seems to cause a lot of issues, even if you clear them.
 

Lunnig149

Member
What if you create a new list and destroy it each time, instead of using the same list? Reusing lists this way seems to cause a lot of issues, even if you clear them.
I used a new list in each time and destroyed it after each time. Did not work.

So I started checking and found the following:

1) Run the game with "show_debug_message(object_get_name(object_index))" in the begin_step event to find the last instance before the crash.
Result: The object of which the code above is take is always the last one called before the crash.

2) Checked the single functions in that object with the same method.
Result: The collision_rectangle_list is the last function every time before the game crashes

3) Started a new project and imported the object into it and tried to reproduce the error.
Result: Error could not be reproduced.

4) Remembered a similar incident in one of my studies project and decided to move the object causing the error in the game in the resources -library into another position further down in the resources -library .
Result: Error could not be reproduced. But reoccurred as soon as the object is placed into the original position in the resources-library .


Can someone explain what happened why step 4 has that effect?
Does the resources-library somehow influence the order of the instances in-game?

Sorry for the long text and as always thank you for any kind of input :)
 

TheouAegis

Member
Were these instances added to the room in the IDE? Or were they created via instance_create()?

Resource tree ordering changes the ID of each resource. So object_index 0 will become object_index 1 if you move the first object in the resource tree down one position.
 

Lunnig149

Member
Were these instances added to the room in the IDE? Or were they created via instance_create()?
The object is created via instance_create() which in turn is triggered by me pressing a button. The object calling the instance_create() is higher up the resource tree in both cases (working and not working configuration of the
collision_rectangle_list() )
 
Top