Unable to find instance for object index

Bear98

Member
I'm trying to call a variable's ID and Object Index from an Array, but I keep getting this message:

Unable to find instance for object index 11
at gml_Object_oBattle_Create_0 (line 81) - NewBattleBox(string(SelectedEnemy.name) + " Would like to fight!");


I'm new here and at programming 😅. Some assistance would be greatly appreciated!
 

Bear98

Member
SelectedEnemy is supposed to take on an Object ID in the array.

All the enemies have a Parent to inherit some basic stats: HP, DEF, Name, etc.
The player collides with an enemy, takes the enemy's Object ID to an array. When the player selects the attack option, they should be able to choose their enemy. After selecting an enemy, the player attacks that specific enemy. The text box will bring up the enemy's stats and say something like "[PLAYER] attacked [ENEMY]".
 

Bear98

Member
Here's the full error code, just in case 😅

############################################################################################
ERROR in
action number 1
of Create Event
for object oBattle:

Unable to find instance for object index 12
at gml_Object_oBattle_Create_0 (line 81) - NewBattleBox(string(SelectedEnemy.name) + " Would like to fight!");
############################################################################################
gml_Object_oBattle_Create_0 (line 81)
 

Nidoking

Member
SelectedEnemy is supposed to take on an Object ID in the array.
Okay, fine. You've got an object ID. Where's the instance? The error message is perfectly clear. It says there's no instance of whatever object SelectedEnemy is. Where are you checking to see whether there is an instance of that enemy?
 

Bear98

Member
I believe the instance is from the Enemy Object the Player collides with.
The Parent Enemy initializes some arrays to place the enemies in, like so:
GML:
///MASTER ENEMY LIST
enemyList[0] = oGhost;
enemyList[1] = oMummy;
enemyList[2] = oVampire;

//MY ENEMY GHOST
MyGroup[0] = self.object_index;
MyGroup[1] = enemyList[irandom_range(0, 2)];
MyGroup[2] = enemyList[irandom_range(0, 2)];
Then, I count how many Enemies will appear in battle using this:
GML:
for (i = 0; i < irandom_range(1, 3); ++i){
    EnemyBattle[i] = MyGroup[i];
}
When the Player collides with an Enemy Instance, they take the Enemy's ID and Object Index and I believe it's convert it to an Enemy Party. I believe that each enemy that appears in the next Room are all separate instances.

GML:
enemyID = other.id.object_index;

for (i = 0; i < array_length(enemyID.EnemyBattle); ++i){
    enemyParty[i] = enemyID.EnemyBattle[i];
Another Object, I called oBattle, is activated as soon as the Battle Room is loaded in; oBattle will receive an Alarm to draw all the Enemies needed.

GML:
if (PrepareEnemy == true){
///THIS SUMMONS ENEMIES TO THE ROOM
    for (i = 0; i < array_length(enemyParty); ++i){
        instance_create_layer(450 + (i * 125), 200, "Instances", enemyParty[i]);
        PrepareEnemy = false;  
    }
}
Is that what you mean?
Did I call the instance correctly? If at all?
Is it illegal?
 
Last edited:

TheouAegis

Member
Well your error message is pointing to oBattle's create event, so the alarm doesn't even matter. The question is then why is the create event running code on a variable that typically wouldn't be set until after the create event has already run? What is oBattle's full Create Event?

Does this error occur at the very first battle, or doesn't work on the first battle and not afterward?
 

Yal

🐧 *penguin noises*
GMC Elder
Chances are that
SelectedEnemy
is not set correctly (it's set to an object that there are no instances of in the room, so it can't find any instance of it when trying to read its name). Try wrapping an if(instance_exists(SelectedEnemy)){ around the block to make sure it only tries reading the data if the enemy exists.


Also keep in mind that you can change the instance creation order if you need some other object to be created first that would set the variables, if you don't set this order yourself they're basically run in a random order and you can't rely on other objects being present in the create event.
 

Bear98

Member
Well your error message is pointing to oBattle's create event, so the alarm doesn't even matter. The question is then why is the create event running code on a variable that typically wouldn't be set until after the create event has already run? What is oBattle's full Create Event?

Does this error occur at the very first battle, or doesn't work on the first battle and not afterward?
I'm wanna make sure that when I'm calling an Enemy's stat, It runs properly. Should I run it somewhere else instead? As for the error, it occurs as soon as it generates the Battle Room.

My code is very messy, so I'll try to hide it. 😫

GML:
/// @desc Turn Based Battle

#region //TEST
x1 = RESOLUTION_W/2;
y1 = RESOLUTION_H-200;
x2 = RESOLUTION_W/2;
y2 = RESOLUTION_H

x1Target = 0;
x2Target = RESOLUTION_W;

lerpProgress = 0;
textProgress = 0;

textMessage = "Sphinx of black quartz, judge my vow.";
background = 0;
#endregion

#region //Draw Battle Actions
a_text[0] = "ATTACK";
a_text[1] = "DEFEND";
a_text[2] = "SKILL";
a_text[3] = "ITEM";
a_text[4] = "RUN";
#endregion

////ENCOUNTER MESSAGE
//encounter[0] = enemyID.name + " blocks the way!";
//encounter[1] = "You encountered " + enemyID.name + "!";
//encounter[2] = "Suprise! " + enemyID.name + " Came to rob you!";

//ERASE MESSAGES
ds_message = ds_list_create();

//RUN PROTOTYPE
RUN = 0;

//TEXT



//INTIALLIZE
EnemyNum = 0;
EnemyDefeat = false;
RUNAWAY = false;
e = 0; //How many enemies in this party

selected_option = 0; //Where is the arrow hovering over?
SelectEnemy = 0;    //target which enemy?
battleOver = false;
player_turn = true;
messageCounter = 0;
showBattleText = false; //displays text boxes

messageTimer = 0;
messageAlarm = 30;

enemyTimer = 0;
enemyAlarm = 15;

//SET UP CONTROLLER
globalvar ChooseEnemy,PlayerAttack, CurEnemyParty, EnemySelect;

ChooseEnemy = false;        //IS THE PLAYER CHOOSING AN ENEMY?
EnemySelect = 0;        //WHAT ENEMY IS BEING ATTACKED?
PlayerAttack = false;    //SEE IS THE PLAYER IS ATTACKING
//CurEnemyParty = 0;

//NewTextBox("You encountered " + string(array_length(enemyParty)) + " Enemies!");
for (var e = 0; e < array_length(enemyParty); e++){


    
    //with (enemyParty[e]){
    //    SelectedEnemy = other.id.object_index;
    //}
    SelectedEnemy = array_get(enemyParty, e);
    
    //NewBattleBox(SelectedEnemy.name);
    //SelectedEnemy.target = true;
    if (instance_exists(SelectedEnemy)){
        NewBattleBox(string(SelectedEnemy.name) + " Would like to fight!");
    }
    //EnemySelect = enemyParty[e].id.object_index;

}
 

Bear98

Member
Chances are that

is not set correctly (it's set to an object that there are no instances of in the room, so it can't find any instance of it when trying to read its name). Try wrapping an if(instance_exists(SelectedEnemy)){ around the block to make sure it only tries reading the data if the enemy exists.


Also keep in mind that you can change the instance creation order if you need some other object to be created first that would set the variables, if you don't set this order yourself they're basically run in a random order and you can't rely on other objects being present in the create event.
Should I wrap it around everytime I use SelectedEnemy?
I tried to do this in oBattle's Creation:

Code:
if (instance_exists(SelectedEnemy)){
        NewBattleBox(SelectedEnemy.name + " Would like to fight!");
}
But the text never shows up.
Currently, I'm trying to successfully recall different enemy names. After that, I'm going to attempt to make it so the Player can target a specific enemy.
 

Nidoking

Member
I believe
This is a bad way to start a post about your own code. There is no room for belief in programming.

I don't see you creating enemy instances during this event. Why are you doing whatever NewBattleBox is during the Create event? Why can't that be done during, say, Room Start, when the instances will exist?

I do see you using globalvar, which isn't a thing. Get rid of that. Type global. like everyone else.
 

Bear98

Member
This is a bad way to start a post about your own code. There is no room for belief in programming.

I don't see you creating enemy instances during this event. Why are you doing whatever NewBattleBox is during the Create event? Why can't that be done during, say, Room Start, when the instances will exist?

I do see you using globalvar, which isn't a thing. Get rid of that. Type global. like everyone else.
Thank You, NidoKing! I changed the Create event to a Room Start event and moved the Instance creation code to the Room Start. Now all the Enemy's names are displayed. Thank you so much!❤
 

chamaeleon

Member
Should I wrap it around everytime I use SelectedEnemy?
I tried to do this in oBattle's Creation:

Code:
if (instance_exists(SelectedEnemy)){
        NewBattleBox(SelectedEnemy.name + " Would like to fight!");
}
But the text never shows up.
Currently, I'm trying to successfully recall different enemy names. After that, I'm going to attempt to make it so the Player can target a specific enemy.
instance_exists() returning any value of any kind will not have anything whatsoever to do with SelectedEnemy.name, if there's more than one. If there's only one instance, it will so happen that SelectedEnemy.name will be the name of this instance, but if you have more than one, SelectedEnemy.name will pick the name of some instance over which you have very little control. You need to figure out what your actual selection mechanism is, and assign the instance id of it to a variable, rather than trying to use the SelectedEnemy object as some kind of "do what I mean, not what I write" selection mechanism.
 

Bear98

Member
Okay... So...
While I'm able to successfully recall the instant's name, if I try to recall any other variables, it comes up as "Unable to find instance for object index". Does anyone know what causes that?
 

chamaeleon

Member
Okay... So...
While I'm able to successfully recall the instant's name, if I try to recall any other variables, it comes up as "Unable to find instance for object index". Does anyone know what causes that?
Not without code and the error message, if it's now different from what you posted in the beginning. I'd recommend using the debugger and put a breakpoint on the line where the crash happens and see what instance is running code, and inspect its variables, etc.
 

Bear98

Member
I retraced some of my steps, and found that I was only calling the arrays, not getting the array variables. I'm able to find the object index, but ran into another problem: It's says that 132 argument is an Array.

GML:
for (i = 0; i < array_length(global.enemyParty); ++i){
        global.Name = array_get(global.enemyParty.NAME, i);
        global.Candy = array_get(global.enemyParty.CANDY, i);
        global.Exp = array_get(global.enemyParty.EXP, i);

        Victory(global.Name, global.Candy, global.Exp);
}
Is this the correct way to pass an array variable to a script?
 

rytan451

Member
What's global.enemyParty? You're calling array_length(global.enemyParty), so it needs to be an array. However, you're also getting the value global.enemyParty.NAME and finding the i-th element in it, which means that global.enemyParty must be either be an instance or a struct, and global.enemyParty.NAME must be an array.

Did you mean, perhaps, global.Name = global.enemyParty[i].NAME? That is, instead of "get the i-th element of global.enemyParty.NAME", did you mean to do "get the property 'NAME' of the i-th element of global.enemyParty"?
 

Bear98

Member
Sorry for the inactivity, life got busy
global.enemyParty is an array that holds individual enemy info (i.e. bat's stats, item drops, name, etc.).
I want to get the names of global.enemyParty to print it out on a message.
 

TheouAegis

Member
Then you need to use an array format.

global.Name = global.enemyParty[i, NAME];

Or in 2.3

global.Name = global.enemyParty[i][NAME];

The point is, you don't reference arrays with dot notation, you use brackets.


Edit: Fixed
 
Last edited:

Bear98

Member
Then you need to use an array format.

global.Name = global.enemyParty[i, NAME];

Or in 2.3

global.Name = global.enemyParty[i][NAME][I];[/I]

The point is, you don't reference arrays with dot notation, you use brackets.
Thank you for your help, but what does [I] represent?
 
I do see you using globalvar, which isn't a thing. Get rid of that. Type global. like everyone else.
Nah, globalvar should definitely not be used like this for single values, but until gamemaker releases a way to create static utility classes like you can in a real programming language there are uses for it. I'll be damned if I have to read my own code and see some ugly bull💩💩💩💩 like

global.SoundFxPlayer.play("grunt");
^^ eww

If gms ever drops support and I have to use macros in order to like how my code looks I guess I will.

SoundFxPlayer.play("grunt")
^^ nice

The problem with the way OP is using globalvar is that they are polluting a global namespace with single values, and using the global keyword doesn't really help with that at all. It just shifts the effect of the sloppiness to being ugly to read instead of hard to follow.
 
Top