• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Legacy GM [SOLVED] Instance_create from an array

S

Sethis

Guest
Hi guys,

I'm currently working on a little side project (an endless runner) but I'm stuck (since almost 3h now) because of something that I can't wrap my head around. Maybe someone else might spot what I might overlooked, so here I am, asking for help.

First, I have a script that store in a 2D array the x, y, and name (get_object_name) of every obj_obstacle in the room.
Code:
/// Count how many instance there is in the room and store them (with their position) in an array

var i;
var current_instance;

// Store every instance in a 2D array (x [i,0] , y [i,1]), obj type [i,2]

for (i = 0; i < instance_number(obj_obstacle); i++) {
    current_instance = instance_find(obj_obstacle,i);
    portion_storage[i,0] = current_instance.x;
    portion_storage[i,1] = current_instance.y;
    portion_storage[i,2] = object_get_name((current_instance).object_index); // Object type (= name, ex: "obj_square") (it's a string)
}

return portion_storage;

It's saved in the globalvar array named "room_array_test".

Then, in an other room, I want to recreate every instances of the obj_obstacle at the same position. I have a controler object (obj_processor) who do that in a create event :

Code:
for (i = 0; i < array_height_2d(room_array_test); i++) {
    show_message(room_array_test[i,2])
    instance_create(368+room_array_test[i,0],room_array_test[i,1],room_array_test[i,2]);
}

Problem : it's not working, though the show_message give me the good name (either obj_square or obj_bigSquare). Seems like it's coming from the third argument of instance_create, cause I meddled with it (tried with a specific object like obj_square (which works) and "obj_square" (which doesn't).

I found a workaround, but it's just an ugly way of doing things, and I want to understand why it didn't works the first time :

Code:
for (i = 0; i < array_height_2d(room_array_test); i++) {
    show_message(room_array_test[i,2])
    if room_array_test[i,2] == "obj_square" {
        instance_create(368+room_array_test[i,0],room_array_test[i,1],obj_square);
    }
    else if room_array_test[i,2] == "obj_bigSquare" {
        instance_create(368+room_array_test[i,0],room_array_test[i,1],obj_bigSquare);  
    }
    else {
        instance_create(368+room_array_test[i,0],room_array_test[i,1],obj_trigger);
    }
}

Anyone ? :)

Thanks in advance for taking the time to help me.
 
L

Laurent57

Guest
Hi, maybe you must use a global array global.blabla[x,y] else you're array is reset when you change the room.
 
S

Sethis

Guest
Yes, I just edited my post because I forgot to precise that indeed I stored the result in a global array :)

I should insist on the fact that it's working perfectly if not for the third argument of instance_create.
 

Hyomoto

Member
In this case you shouldn't see the object name, that's a string and not an object id. You can use @Nathan Laing's suggestion to fix it, however, if you get rid of object_get_name it will return the same result without having the overhead of looking up the object name, then converting that name back to an object index.

If you want to display the name for debug purposes, you would use object_get_name in show_message, where the name is useful.
 
S

Sethis

Guest
In this case you shouldn't see the object name, that's a string and not an object id. You can use @Nathan Laing's suggestion to fix it, however, if you get rid of object_get_name it will return the same result without having the overhead of looking up the object name, then converting that name back to an object index.
First of all, thanks to all of you for answering so fast :)

Then, I must say that I'm not sure I understood what you meant (both of you). Why would I want the object index (if not to get the name of the object) to create an instance ? If I'm not mistaken, instance_create requier the name of the object. Is it working with the index too ?

Anyway, I don't get how I could use asset_get_index in my situation (might be a tad bit tired too ...)

Simply, what I wanted to do was :
- loop through all the instances of the object "obj_obstacle" (the parent) in the room and store the position and wether it's the child object "obj_square" or "obj_squareBig" (I do have a third object named obj_trigger but there's only one in the room).
- go in another room and recreate the instances in their respective position and type (if it's a square or bigSquare)

That's why my though of train was such :
-in the loop, in the first room, get the "object.index" of the instance being stored ... not that I need it but for object_get_name which requier the index (if it was the id it would have been easier I think) ... (thb, it might be object_index that I don't understand well).
- in the second room, use instance_create to create the good type of instance (square or bigSquare) at the right place. What I don't understand (bis) is that even though when using show_message(room_array_test[i,2]) I get the right name, and even in debugging mode the array contain the right string (obj_square or obj_bigSquare), instance_create(x,y,room_array_test[i,2]) don't create the instance (or even create another one altogether if I meddle with the code).

Sorry I had to repeat myself, I wanted to explain why I did code like that, and what exactly I'd like you all to explain to me why it's not working properly :)

Sorry again to be such a pain :p
 
Last edited by a moderator:

FrostyCat

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

instance_create() takes an object ID as its third parameter. That is a numeric value, not a string. Your original code does not work because you were passing strings returned by object_get_name() into instance_create().

So that you stop believing that an object ID is a string, I suggest that you run the following example:
Code:
show_message(obj_square);
show_message("obj_square");
The first line would show a numeric value, the second would show a string. This is conclusive proof that these two are not the same.

The purpose of asset_get_index() is to convert a string name back into the numeric ID that functions like instance_create() can use. This allows you to piece together resource IDs from variables (e.g. asset_get_index("obj" + shape)) or load resource names from external input. But in your strictly internal situation, converting to string names and then back to object IDs is a needless round-trip. Hyomoto is suggesting that you drop the object_get_name(), so that the actual object ID is stored into the array and instance_create() can directly act on it.
Code:
portion_storage[i,2] = current_instance.object_index;
Code:
instance_create(368+room_array_test[i,0], room_array_test[i,1], room_array_test[i,2]);
For future reference, if you do need to persist the values in a file, then that's when you should save string names (i.e. the return value of object_get_name()) because object IDs can shift if you rearrange objects on the resource tree. Use object_get_name() while writing to convert object IDs to string names, and use asset_get_index() while reading to convert string names back into object IDs.
Code:
portion_storage[i,2] = object_get_name(current_instance.object_index);
Code:
instance_create(368+room_array_test[i,0], room_array_test[i,1], asset_get_index(room_array_test[i,2]));
 

Hyomoto

Member
So, just to cover the idea briefly since I think it would explain most of your questions, the short answer is: no. The longer answer is do not confuse bullet_object with "bullet_object". The object_get_name function returns the name of an object as a string. Consider the following:
Code:
instance_create( x, y, "bullet" );
instance_create( x, y, bullet );
The first one will, if it doesn't crash outright, return unexpected behavior. It's literally no different from using "x" instead of x. Every asset has a unique id you can access using a variable, the name is just a string representation of that. So if you get that string, you must convert it back to an id using asset_get_id, but you can skip that by not converting it to a string in the first place.
 
S

Sethis

Guest
Thanks a lot ! Everything is crystal clear now !

I'll fiddle with the code tomorrow and mark the topic as resolved if everything works fine. Thanks again guys, fast and efficient. 5/5, would buy again :D

03/28/18 - Like a charm ! Thanks once more !
 
Last edited by a moderator:
Top