• Hello [name]! Thanks for joining the GMC. Before making any posts in the Tech Support forum, can we suggest you read the forum rules? These are simple guidelines that we ask you to follow so that you can get the best help possible for your issue.

Question - Code What is the correct way to declare 'object' style variables

Starlight

Member
I was on version 2.2.1.3 and using the below code in multiple places without a problem

Code:
move = "EnemyIdle";
move.state = states.idle;

return move;
This worked and I've used it across my game

After updating to 2.2.2.4 I can no longer do this, and get the following error
Code:
FATAL ERROR in
action number 1
of Create Event
for object object_tempEnemy:

unable to convert string "EnemyIdle" to int64
 at gml_Object_object_tempEnemy_Create_0 (line 19) - move.state = states.idle;
Is this a bug or regression in the update?

If not, I don't mind updating my code, but what is the correct way to define a variable that functions this way?

Ex. How do I declare 'move' so that I can use move.var1, move.var2, move.var3 etc. and return the entire structure

What is the variable type I was seemingly implicitly creating before?
 

FrostyCat

Member
Resource IDs are not strings, stop treating them like one.

If EnemyIdle is an object ID or instance ID, get it out of the quotes so that you work with a live ID.
Code:
move = EnemyIdle;
move.state = states.idle;
If that isn't what you want, you would need to work out what you actually wanted and redo every piece of code that contains the same mistake.

Your code shouldn't have worked in the first place, if it ever did it's because you were unlucky enough to have it forgiven badly. Because 2.2.1 and below used to cast non-castable types to 0 when a numeric value is warranted (which the left side of a dot is for an object or instance ID), this whole time you have been creating instance variables for the first object in your resource tree. If there's an instance of that, you wouldn't get an error as 0 would then be a legal target to try assigning variables for, but the absence of an error doesn't mean everything's alright.

This is not a bug or regression in 2.2.2, this is new 2.2.2 behaviour pointing out a problem in your code that 2.2.1 used to incorrectly sweep under the rug.
 

Starlight

Member
Resource IDs are not strings, stop treating them like one.

If EnemyIdle is an object ID or instance ID, get it out of the quotes so that you work with a live ID.
EnemyIdle is not an object ID or instance ID. It is literally a string used as a string for debugging to display what state an object is in. It just so happened to also work to declare 'move' for me so I can declare properties on it (Or whatever they are when referenced by thing.varName)

I appreciate the condescending tone though. If you note in the OP, I was fully prepared for this to be wonky unintended behaviour, and asked how I should do this properly.

Your code shouldn't have worked in the first place, if it ever did it's because you were unlucky enough to have it forgiven badly. Because 2.2.1 and below used to cast non-castable types to 0 when a numeric value is warranted (which the left side of a dot is for an object or instance ID), this whole time you have been creating instance variables for the first object in your resource tree. If there's an instance of that, you wouldn't get an error as 0 would then be a legal target to try assigning variables for, but the absence of an error doesn't mean everything's alright.

This is not a bug or regression in 2.2.2, this is new 2.2.2 behaviour pointing out a problem in your code that 2.2.1 used to incorrectly sweep under the rug.
This is the actual information I needed to know to understand what was happening. Makes sense, thank you.

Is there a correct way to declare move, so that I can do for example:

Code:
move.name = "EnemyIdle"
move.state = states.idle

return move
Or is this simply not a thing in gamemaker and I just need to refactor how I'm approaching this?
 
Last edited:

FrostyCat

Member
Is there a correct way to declare move, so that I can do for example:

Code:
move.name = "EnemyIdle"
move.state = states.idle

return move
Or is this simply not possible and I need to refactor everything?
There are 2 ways in which you can do it the way you described.

The first is creating a new automatically self-deactivated object type to serve as a carrier for instance variables.
Code:
// obj_data_unit Create
instance_deactivate_object(id);
Code:
// Your script
var move = instance_create_depth(0, 0, 0, obj_data_unit);
move.name = "EnemyIdle"
move.state = states.idle
return move;
The second is using an array with an enum. Note that the enum declaration should only appear once in your project.
Code:
// Put this in a new script that's never called anywhere
enum data {
  name,
  state
}
Code:
// Your script
return ["EnemyIdle", states.idle];
Then you would index the returned array using the enum (e.g. arr[data.name]).
 

Starlight

Member
There are 2 ways in which you can do it the way you described.

The second is using an array with an enum. Note that the enum declaration should only appear once in your project.
Code:
// Put this in a new script that's never called anywhere
enum data {
  name,
  state
}
Code:
// Your script
return ["EnemyIdle", states.idle];
Then you would index the returned array using the enum (e.g. arr[data.name]).
This is what I was thinking and then you replied. Just refactored everything by changing move to an enum

Code:
var frameMove = [];
frameMove[move.name] = "EnemyIdle"
frameMove[move.state] = states.idle;

return frameMove
This gives me the behaviour I wanted, albeit a bit more verbose.

Thank you!
 
Top