• 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!

[solved] Best way to setup enemy variables.

S

Sake_v2

Guest
Let's say I have 3 enemies, and they should have 3 different sprite animations. Instead of having 3 different enemy objects with walkSprite set on create event accordingly (doing so, creating 30 enemies would create 30 variables when you only need 3), I have an oEnemyControl object with an array like this

enemySetup[0,0] = sEnemy1Walk;
enemySetup[0,1] = sEnemy1Power;

enemySetup[1,0] = sEnemy2Walk;
enemySetup[1,1] = sEnemy2Power;

enemySetup[2,0] = sEnemy3Walk;
enemySetup[2,1] = sEnemy3Power;

and I have a enemy parent object that everytime it needs to call the walk sprite accordingly, uses it like this:
var walksprite = oEnemyControl.enemySetup[enemyID,0];
if Moving
{
sprite_index = walksprite;
}
(ignore long and not practical objects and variables names, just an example).
Would you do it any different? Maybe not using arrays? Referencing oEnemyControl over and over could slow the game down? I'm having some performance issues in a project where the "stepevent bar" on show_debug_overlay is not optimal. Thanks
 

Rob

Member
I would assign things to an instance when it's created like this:

Code:
enemy = instance_create(blah blah blah);
enemy.val = 0;

[Inside enemy]
enemySprite = enemySprites[val];
draw_sprite(enemySprite, blah blah);
I don't know if that's any "faster" than what you suggested, it's just how I do things usually.
 

TheouAegis

Member
If you're having slowdown, then making MORE variables is better. The more variables you have, the fewer operations you need to run. In your example code, you're creating 1 variable of walkspr (1 operation), loading the controller's id into a memory register (1 more operation), loading the enemyID into another register (1 more operation), loading 0 into another register (1 more operation), fetching the enemySetup array (1 more operation) and storing the result into the walkspr variable (yet another operation). On the other hand, if you just gave each enemy their own walkspr variable, then each step would just be a single read operation.
 
S

Sake_v2

Guest
If you're having slowdown, then making MORE variables is better. The more variables you have, the fewer operations you need to run. In your example code, you're creating 1 variable of walkspr (1 operation), loading the controller's id into a memory register (1 more operation), loading the enemyID into another register (1 more operation), loading 0 into another register (1 more operation), fetching the enemySetup array (1 more operation) and storing the result into the walkspr variable (yet another operation). On the other hand, if you just gave each enemy their own walkspr variable, then each step would just be a single read operation.
Yes. That's how it was before. But the problem with that is that what I said with only 2 sprites was an example, in the project itself the enemies need so many custom values, damage, sprites, etc, that it very well could get to 30 variables per enemy to get everything right. In a game where there could be dozens of them at the same time, having the game jumping from using 30K at task manager to almost 300K super fast because of a couple enemies didn't seem like the best idea.
I'm sure the slowdown is not only because of that and there are more things to optimize, I was just looking to see if anybody had a better suggestion
 

JackTurbo

Member
You should be able to haves dozens of enemies as separate objects without slow down.

I think you might putting the kart before the horse here and perhaps trying to optimise prematurely.

If you are actually getting slow down are you sure it's the enemies causing it? And if so what part of the enemies codebase?

I just think youre potentially going to make your enemies in your project much more abstract with this approach which is be cincercon about it being manageable as the project grows.
 
S

Sake_v2

Guest
You should be able to haves dozens of enemies as separate objects without slow down.

I think you might putting the kart before the horse here and perhaps trying to optimise prematurely.

If you are actually getting slow down are you sure it's the enemies causing it? And if so what part of the enemies codebase?

I just think youre potentially going to make your enemies in your project much more abstract with this approach which is be cincercon about it being manageable as the project grows.
Thank you for your reply, I think this was actually my mistake and didn't correctly express myself. I actually believe the slowdown is not being caused by the code in question, the slowdown is not the problem as I'm not currently optimizing the game. All I wanted with this thread was simply know if people had a better suggestion to the code I posted originally, in where I have, for an example, 30 variables to each enemy, how would people use it personally.

I tried on the beginning, just on the create event of each enemy set those variables, but with 100 enemies on the screen, that quickly turned into 3000 variables unnecessarily, instead of only 30. So the game jumped from using 30K of RAM to 300K. So I prefered to, instead, create a separate enemyControl object in which those variables are set in an array, so the enemies can reference it. Instead of 3000 variables, now I have 30. Much better. But now, everytime my enemies need to access their correct variables, they need to reference that array on a different object with the correct ID, like this:

Code:
if moving
{
   sprite_index = enemyControl.enemySetup[enemyID,0];
}
if superPower
{
   sprite_index = enemyControl.enemySetup[enemyID,1];
}
I'm not exactly sure how slow this code is, considering again, I need to fetch about 30 variables. I thought of doing a couple of things, maybe copying the array at the beginning of the code in a local var to easy access, but if there are several types of enemies in the game, copying a huge array with a "tall height" could be costly aswell. I thought about using different arrays, all sorts of things, but again, I'm not sure about which combines the two worlds as much as possible in regards to maintaining performance and not having a huge RAM cost.

So far TheouAegis commented on actually having more variables, but then I'm using 3000 variables again, and Rob apparently does it the same way that I do? Or very similar at least.
 
Last edited by a moderator:

Smiechu

Member
First of all...
Objects are not instances! It doesen't really matter if you have the same variable names in every object or not...
Every instance have it's own set of variable values saved in ram.
Second... read about parent/child code inheritance in GMS. I think you could save a lot of time utilizing it.
 
S

Sake_v2

Guest
First of all...
Objects are not instances! It doesen't really matter if you have the same variable names in every object or not...
Every instance have it's own set of variable values saved in ram.
Second... read about parent/child code inheritance in GMS. I think you could save a lot of time utilizing it.
Uh... what? I'm almost assuming you replied to the wrong thread. It has nothing to do with "variable names" and I use inheritance all the time, including on the enemies, nothing to do with the topic also.

Anyway, appreciate the responses. I might consider this topic solved and keep using my way or just test a bunch of things later.
 

JackTurbo

Member
How many enemies are you expecting to have activated at any one time? - I'm guessing if you're concerned about ram usage from variables then you're hoping to have many hundreds?

Also reading from arrays is very fast so I doubt that would be a significant issue.
 

Smiechu

Member
Yes I'm sure... you have no idea how parenting works, and what object and instance is.
If you have parents and childs you don't need to refer the parent object/instance with dot operator. If the oEnemyControl is the parent and inheritence is on, than by creating an instance of the child object you have the arrays of the parent object already inside! Now every instance of your enemy objects carries whole load of unneeded data.

What is the easiest method.

Parent object - create event:
walksprite = spr_dummy;

In parent you define all the variables with default values.

Child object create event:
Event_inherits();
walksprite = spr_enemy_1_walk;

No arrays, no reading from other instances, and you only need to define the variables which have other values than default.

Sorry if im not clear enough but I'm writing from handy.
 

TheouAegis

Member
That's still 3000 variables instead of 30.

You could create a set of data structures at the start of the game (use enumerators to keep track of which goes to what), since data structures are persistent globally. Then read from the data structures using accessors. Haven't compared speeds, it's just an option.
 
S

Sake_v2

Guest
How many enemies are you expecting to have activated at any one time? - I'm guessing if you're concerned about ram usage from variables then you're hoping to have many hundreds?

Also reading from arrays is very fast so I doubt that would be a significant issue.
Yes. Many hundreds. That's why variable amount became a concern to me, because it went to more than 300K RAM usage.

Yes I'm sure... you have no idea how parenting works, and what object and instance is.
If you have parents and childs you don't need to refer the parent object/instance with dot operator. If the oEnemyControl is the parent and inheritence is on, than by creating an instance of the child object you have the arrays of the parent object already inside! Now every instance of your enemy objects carries whole load of unneeded data.

What is the easiest method.

Parent object - create event:
walksprite = spr_dummy;

In parent you define all the variables with default values.

Child object create event:
Event_inherits();
walksprite = spr_enemy_1_walk;

No arrays, no reading from other instances, and you only need to define the variables which have other values than default.

Sorry if im not clear enough but I'm writing from handy.
Did you just say I have no idea how inheritance works? lol. I just told you this is not coming from a beginner, and I use inheritance all the time. If I do what you just suggested, I would have 3000 variables again, which is the problem I'm actually trying to avoid.

That's still 3000 variables instead of 30.

You could create a set of data structures at the start of the game (use enumerators to keep track of which goes to what), since data structures are persistent globally. Then read from the data structures using accessors. Haven't compared speeds, it's just an option.
Hmm. I will test it. Thanks for the suggestion. And yes, I already use enumerators with the arrays. It would get too messy trying to memorize what's what.
 

Smiechu

Member
I'm very sorry for my ignorance. I've misunderstood your point the first place.
I can only say that in era where simplest mobile devices have minimum 1GB of RAM, looking to save 270kB of memory is quite ridiculous.
The best you can do is simply make a test project comparing cpu load of both solutions.
In my opinion simple version with individual variables is faster.
 
S

Sake_v2

Guest
I'm very sorry for my ignorance. I've misunderstood your point the first place.
I can only say that in era where simplest mobile devices have minimum 1GB of RAM, looking to save 270kB of memory is quite ridiculous.
The best you can do is simply make a test project comparing cpu load of both solutions.
In my opinion simple version with individual variables is faster.
No problem. It was actually 300K on the task manager, not 300kb, that's why I had to change it. I will test a couple of options, yes. Appreciate the answers, I consider this solved.
 
Top