Instance_deactivate_region causes slowdown?

Khao

Member
Mostly out of fun, I started importing a complete, non-commercial game I made a couple of years ago from Game Maker 8 to Game Maker Studio. Surprisingly enough, it went pretty smoothly outside of some audio issues and some trigger events here and there that needed to be replaced, at least when it comes to making the game work.

Except the game works incredibly slowly now for some reason (15-20fps out of the needed 60).

After some research and testing, I realized that the problem was in the code that deactivates object outside the view. For some reason I just can't understand, using it slows the game down to a crawl, while turning it off leaves it working perfectly (over 500fps according to the debugger).

I tried deactivating instances every few steps with an alarm, but then the game will noticeably stutter when the alarm's activated.

The only thing I'm doing right now in the code is activating every instance in the room, deactivating the ones outside the view, and finally activating a few objects that absolutely need to be active when outside the view. This used to work back in GM8, but evidently something changed and I guess my code needs to change too if I want it to work properly.

Is there a better way of doing this? It seems a bit counter-productive to use a code that deactivates objects if it's gonna leave the game running slower rather than faster, which is pretty much the biggest reason you'd do such a thing... But the truth is, I still actually need to deactivate a lot of objects outside the view, because leaving them active leads to a ton of unpredictable problems, and I'd rather not have to reprogram all those objects when the actual game was already completed.
 

Jakylgamer

Member
step event:
Code:
instance_deactivate_all(true);
instance_activate_region(view_xview[0] - 128, view_yview - 128, view_wview[0] + 192, view_hview[0] + 192, true);
//activate other stuff if needed

this works perfectly and no slow down.
 

Khao

Member
Literally the opposite of what I'm doing. Brilliant. Gonna try that.

EDIT:

Weird.

It is actually running faster than before, and I'm guessing it's because deactivating everything and then activating inside the view actually handless less objects at a time when compared to activating everything and then deactivating outside the view. But it's still not anywhere near full speed.

Tested a few more stuff, and it seems like the problem actually comes from activating objects after that. If I don't activate any objects in the end, the game works flawlessly, while activating leaves the game running at less than half the right speed at worst. And I'm confused by that because I'm not activating any more than 11 objects at a time, which really isn't a lot.

Is instance_activate_object() really that slow? Are there any alternatives?
 
Last edited:

Khao

Member
EDIT: Aw shoot, sorry about the double post. I don't know why, but I expected them to merge automatically, but I guess this forum doesn't do that.
 

Jakylgamer

Member
i guess it would depend on how many things you are activating at once, there might be something creating too many objects causing the lag.
 

GMWolf

aka fel666
I belive the manual itself specifically discourages activating and deactivating instances everystep.
Insteead, activate a slightly larger region of the screen, and only update every couple steps (using an allarm for instance).
a much more efficient solution yet would be to split up your scene into chunks, and the activate a chunk as you walk towards it, and deactivate one as you walk away from it.
This is much better as it means you do not change anything so long as your view stays in the same area. It also minimizes the number of times you need to reactivate objects when moving quickly by ensuring these chunks are large enough.
 

RangerX

Member
You need to limit as much as possible to have objects activating/deactivating at the same time. Right now you're giving a toll on the engine for no good reason. You should do only 2 things:

1) Have an "outside view event" in each object you want to be able to deactivate. In that event you simply put the deactivation code like: instance_deactivate_object(id);
This means this instance of X object will deactivate itself and only itself.

2) Have your Hero character or object that is always in the center of the screen activate a region every step (or every 5 step, 10 steps, etc). That region should simply be the screen:
instance_activate_region(view_xview,view_yview,view_wview,view_hview,true);

By doing it properly like this, your game will run smooth as a baby's butt.
 

Khao

Member
You need to limit as much as possible to have objects activating/deactivating at the same time. Right now you're giving a toll on the engine for no good reason. You should do only 2 things:

1) Have an "outside view event" in each object you want to be able to deactivate. In that event you simply put the deactivation code like: instance_deactivate_object(id);
This means this instance of X object will deactivate itself and only itself.

2) Have your Hero character or object that is always in the center of the screen activate a region every step (or every 5 step, 10 steps, etc). That region should simply be the screen:
instance_activate_region(view_xview,view_yview,view_wview,view_hview,true);

By doing it properly like this, your game will run smooth as a baby's butt.
Would it be a good idea if instead of adding that to every single object, I just add this code:
Code:
if instance_exists(obj_example)
{
     with (obj_example)
     {
          if x < view_xview || y < view_yview || x > view_xview + view_wview || y > view_yview + view_hview
          {
               instance_deactivate_object(self);
          }
     }
}
Or something along the lines for each object I want to deactivate? Or would all those checks make it slower than just using events in each object?

I'm asking because... There really are a lot of objects and doing this'd save a ton of work. Plus, it'd be a lot more manage-able to have it all in the same spot. This game was finished already, and I can't exactly go back in time and tell myself to code better to prepare for all these things. =P But if the other way's faster, it's probably worth the effort.
 

RangerX

Member
Your idea still is more toll on the engine than what I suggest.
Even if you game is basically finished, you need it to run better so.... take the time to put ONE line of code in all your concerned objects.
You can even copy the code block and just paste it in all your object. This can go quite fast me thinks.
 

Khao

Member
Kay, perfect.

The amount of objects I need to deactivate's actually a lot less than I expected, so I'd have to be an idiot not to do it the right way. Thanks a lot for the advice! I'm not even halfway done yet and the game's already back to full speed. Would bet anything it's already more stable than the Game Maker 8 version.
 
M

Misty

Guest
What I've noticed, is that the 3D part of GM' doesn't have built in Frustum culling.

In my opinion, Frustum culling is pointless without occlusion culling, because you might as well have a steady lag rather than a lag whenever the player turns a certain direction.

That being said, there is a rudimentary way to have frustum culling using instance_activate_region.
 

Carnivius

Member
You need to limit as much as possible to have objects activating/deactivating at the same time. Right now you're giving a toll on the engine for no good reason. You should do only 2 things:

1) Have an "outside view event" in each object you want to be able to deactivate. In that event you simply put the deactivation code like: instance_deactivate_object(id);
This means this instance of X object will deactivate itself and only itself.

2) Have your Hero character or object that is always in the center of the screen activate a region every step (or every 5 step, 10 steps, etc). That region should simply be the screen:
instance_activate_region(view_xview,view_yview,view_wview,view_hview,true);

By doing it properly like this, your game will run smooth as a baby's butt.

This has seemingly fixed the severe and inconsistent frame rate issues my mobile game was having. Ok I've slightly modified it so it's not totally outside the view (but a border around the view for mechanics purposes) but yes this method seems to have improved things for me. :)
 
Last edited:

Drell

Member
Your idea still is more toll on the engine than what I suggest.
Even if you game is basically finished, you need it to run better so.... take the time to put ONE line of code in all your concerned objects.
You can even copy the code block and just paste it in all your object. This can go quite fast me thinks.
Old thread, but it'd be easiest to have all of the objects that need to run the code have some unifying parent object with a user defined event. Then, even if you made new objects that needed to deactivate in the same fashion, you'd simply need to set the parent (or the "grandparent", etc). This is extremely useful for the simplification of debugging; that is, if something's going wrong, it's only going wrong in one place and you don't have to run around remembering all the places the code needs to be corrected.
 

skofrant

Member
I have a question about this topic. I have such a code. But I'm not sure if it is well-written .. What to do to get the best performance?.
I would like all objects outside the region to be inactive, except for those that must be active all the time in the game.
now also the question the region must have the same dimensions as in the hbor and vbor room editor?
The game view I have set to 1280x720
while hbor and vbor i have set to
hbor 800
vbor 500


GML:
instance_deactivate_all(true)
instance_activate_region(view_xview[0]-128,view_yview[0]-128
view_wview[0]+192,view_hview[0]+192,true);
instance_activate_object(obj_game_controller);
instance_activate_object(obj_room_controller);
instance_activate_object(obj_audio_controler)
instance_activate_object(obj_keyhandler);
instance_activate_object(obj_global_controller);
instance_activate_object(par_solid);
instance_activate_object(par_solid_ghost);
 
Last edited:

GMWolf

aka fel666
Deactivating all instances and then activating what's in the view isn't the most efficient solution. But it is plenty efficient enough for the vast majority of projects.

What's a nicer solution is to activate only newly uncovered instances and deactivate instances that move out of view.

From the previous view position and new view position you should be able to get.4 rectangles.
Let's say your view is moving up and to the right, then there will be a rectangle in the top of the view and one to the right of the view where new instances are uncovered, and a rectangle below and another to the left of the view where instances go out of view.
To avoid small movements repeatedly activating and deactivating instances you could use a larger view size when deactivating instances.


Another way to do it would be to split up your instances I to a regular grid.
Then it's easy to see what cells of the grid are close to the view and which are far away. You can then find grid cells that are either in view, or are.close.to the view



But if you are not seeing problems yet, for all but the most complex scenes your code will do just fine.
One way to improve it would be to create a parent object for all things that should be activated/deactivated automatically.
Then when using the activation function you can pass that object.
Then you don't need to reactivate all those controller objects.
 
Last edited:

skofrant

Member
Well, I already see small problems and I would like to control it on an ongoing basis .. Maybe an example? what would be a good solution?
 

GMWolf

aka fel666
I would like to control it on an ongoing basis .
Do you mean every step? I wouldn't recommend that.
It's probably better to reduce how often you do the activation. It's hard to tell exactly what the best scheme is without knowing what data structure GM keeps internally.

I would recommend doing the activation/deactivation with a larger view size, but less often.
It's also possible that spreading out the load may help. For example you could activate instances on even frame, and deactivate instances on odd frames.
It's also possible that doing as much work at a time possible is better, if GM keeps large, and immutable data structures that need to be rebuilt when you activate / deactivate instances.
It's also going to depend on what your scene looks like. If your instances are jittered around evenly then something like spacial partitioning may help you achieve better perf than GMs built in spacial lookups.
If your entities are usually clumped together then it's a whole other ordeal.
 

skofrant

Member
My game is a typical platformer game. The game room are of different sizes. I try to make tileset as much as I can..
I have view everywhere set to 1280x720
 

skofrant

Member
I will stick to my method because I do not know any other methods that are effective in order to optimize the game.

I hope it will be enough for my platform game
one of you mentioned to enlarge the dimensions of the region

I currently have such

GML:
instance_activate_region(view_xview[0]-128,view_yview[0]-128
view_wview[0]+192,view_hview[0]+192,true);
what dimensions do you propose of the region?

The game view I have set to 1280x720
 

skofrant

Member
Could anyone advise me with this?
i have a platform game.
My game view is set to 1280x720
I use this solution to optimize the game, because I don't know another one.
should the region be bigger? if so, what dimensions should it be?
are the objects in the game that must always function well activated correctly?

GML:
instance_deactivate_all(true)
instance_activate_region(view_xview[0]-128,view_yview[0]-128
view_wview[0]+192,view_hview[0]+192,true);
instance_activate_object(obj_game_controller);
instance_activate_object(obj_room_controller);
instance_activate_object(obj_audio_controler)
instance_activate_object(obj_keyhandler);
instance_activate_object(obj_global_controller);
instance_activate_object(par_solid);
instance_activate_object(par_solid_ghost);



someone mentioned other optimization methods in the game before .. but as I say I don't know anything else. I don't even have any example to refer to these other methods.
please help ... certainly of there many uses game optimization and does it on a regular basis ..

thank you
 

Posh Indie

That Guy
First, I would like to commend you on searching for the answer to your problem. Second, I would have to ask that you please put the Necronomicon back where you found it.
 
Top