• Hey! Guest! The 40th (!!!) GMC Jam will take place between February 25th, 12:00 UTC to March 1st 12:00 UTC. Why not join in this very special anniversary jam! Click here to find out more!

GMS 2.3+ place_meeting call inside struct method var causes crash on multiple calls (bug found, please help confirm)

lorewap3

Member
I don't know how to debug this issue I'm having as it's incredibly strange. It seems place_meeting is arbitrarily crashing my project after a few calls. I'm running the debugger when it happens, no error is given, it just silently quits. Cleaning and recompiling the project (even tried a restart) hasn't helped.

What's maddening is I have this method function in a struct (a physics manager for collision, gravity, etc)

GML:
    static On_Ground = function() {

        var _result = false;
    
        //if (place_meeting(objectInstance.x + sign(gravX), objectInstance.y, solidObject) ||    place_meeting(objectInstance.x, objectInstance.y + sign(gravY), solidObject)) {
        if (place_meeting(objectInstance.x + sign(gravX), objectInstance.y, solidObject)) {
            _result = true;
        }
    
        if (place_meeting(objectInstance.x + sign(gravX), objectInstance.y, solidObject)) {
            _result = true;
        }
    
        if (place_meeting(objectInstance.x + sign(gravX), objectInstance.y, solidObject)) {
            _result = true;
        }
        //if (place_meeting(objectInstance.x, objectInstance.y + sign(gravY), solidObject)) {
        //    _result = true;
        //}

        return _result;
    };
Initially it was crashing on the first if. I verified all the variables are set and have values. It kept happening. But it does pass the first check. So I copy/pasted it two more times. All 3 if statements are identical.

It crashes on the 2nd one! Every time! This makes no sense to me. I don't even know how to debug this as there's no reason it doesn't crash on the first one but does on the 2nd.

Like I said...this is maddening!! If anyone has a suggestion on what to check please tell me!

Thanks,
Will P.
 
Last edited:

lorewap3

Member
I believe I've figured out that this is a bug. I created a new project, created a few simple objects and a struct, and am able to recreate it consistently.

If anyone wouldn't mind confirming this I'd much appreciate it. I'm attaching the exported project.

 

FrostyCat

Member
You are running place_meeting from the perspective of a struct, which cannot have a collision mask the way an instance can. This is not a bug, this is undefined behaviour. Use a with block to get back to the perspective of an instance, and pass in the instance ID through either a parameter in the method or a field in the struct.
 

Nidoking

Member
You are running place_meeting from the perspective of a struct, which cannot have a collision mask the way an instance can.
Is this true if it's bound to an instance as a method, though? I was going to point that out, but the post seemed to imply that that's how the function is used.
 

FrostyCat

Member
Is this true if it's bound to an instance as a method, though? I was going to point that out, but the post seemed to imply that that's how the function is used.
This cannot possibly be bound to a instance because of the static keyword. In addition, the post clearly states that it is bound to a struct:
What's maddening is I have this method function in a struct (a physics manager for collision, gravity, etc)
It's incorrect code based on an incorrect understanding of subject perspectives in method calls.
 

Nidoking

Member
This cannot possibly be bound to a instance because of the static keyword.
I don't see what you mean. This works for me:
GML:
funcstruct = function() constructor
{
    static imamethod = function()
    {
        x = 5;
        y = 6;
    };
};

mystruct = new funcstruct();

myfunc = method(self, mystruct.imamethod);
I can have another instance call myfunc and it works just fine.
 

FrostyCat

Member
I don't see what you mean. This works for me:
GML:
funcstruct = function() constructor
{
    static imamethod = function()
    {
        x = 5;
        y = 6;
    };
};

mystruct = new funcstruct();

myfunc = method(self, mystruct.imamethod);
I can have another instance call myfunc and it works just fine.
Your example works because you created a new re-bound method using method(), which is valid. What I'm seeing in the sample is a direct call like this:
Player Create:
GML:
testStruct = new TestStruct(id);
Player Step:
GML:
if (testStruct.TestMeeting()) {
    show_message("Test Meeting True");
};
This sample assumes that TestMeeting() is run from the perspective of the player instance, which is not what actually happens. In reality, TestMeeting() is run from the perspective of testStruct. And that is clearly invalid because structs don't have collision masks.
 

Nidoking

Member
Ah, right, there's a file posted for download. That's clearly the issue, then. I'm just saying that the static keyword doesn't prevent a function from being bound as a method.
 

lorewap3

Member
Aaaah! Thanks guys! You're absolutely right. Thank you for explaining FrostyCat I really appreciate the insight!

I didn't realize place_meeting had that underlying check with the instance's collision mask, although it does make sense now. I thought place_meeting just checked the x/y coordinate passed in against any instances of the object in the room. But that makes no sense without a collision mask as well.

Even if not a bug, I would hope the compiler might be able to crash more gracefully when it happens. The fact that it crashes silently is annoying, but even moreso is the fact that it doesn't crash on the first place_meeting call, but the second. Though, perhaps it's crashing on the 2nd coincidentally because on the first call the mask it's trying to use does match up to some valid mask in the project.

Thanks again you two!
 
Top