1
\$\begingroup\$

So I am trying to make a management game, a space station simulator if you will, with potentially hundreds and thousands of customers entering and leaving the station every game day. So my plan of handling this is to first create a persistent object called oManager. Over the course of the game, oManager will continuously spawn instances of this object called oPerson.

The part of oManager that spawns person:

global.dailyflow = 100;
show_debug_overlay(true);
var number_a_day = irandom_range(ceil(global.dailyflow*0.6),global.dailyflow);
trader_base = floor(number_a_day*0.02);
trader_extra = floor(trader_base*(1+global.trader_modifier/100));
tourist_base = ceil(number_a_day*0.1);
tourist_extra = ceil(tourist_base*(1+global.tourist_modifier/100));
passerby_base = ceil(number_a_day*0.53);
passerby_extra = ceil(passerby_base*(1+global.passerby_modifier/100));
shopper_base = ceil(number_a_day*0.25);
shopper_extra = ceil(shopper_base*(1+global.shopper_modifier/100));
mercenary_base = floor(number_a_day*0.1);
mercenary_extra = floor(mercenary_base*(1+global.mercenary_modifier/100));

repeat(trader_base+trader_extra){
    with instance_create_layer(0,0,"instances",oPerson){
        guy_type = 0;
        event_user(0);
    }
}

repeat(tourist_base+tourist_extra){
    with instance_create_layer(0,0,"instances",oPerson){
        guy_type = 1;
        event_user(0);
    }
}

repeat(passerby_base+passerby_extra){
    with instance_create_layer(0,0,"instances",oPerson){  
        guy_type = 2;
        event_user(0);
    }
}

repeat(shopper_base+shopper_extra){
    with instance_create_layer(0,0,"instances",oPerson){
        guy_type = 3;
        event_user(0);
    }
}

repeat(mercenary_base+mercenary_extra){
    with instance_create_layer(0,0,"instances",oPerson){
        guy_type = 4;
        event_user(0);
    }
}

Each oPerson instance decides on how many days he stays, where he would go to and how much money he spends each day, with much more to come in the future. However, the problem I am currently facing is that the game would just crash after about one game day. I think the problem is there are just too many instances and the game just cannot handle it. I tried to create only one oPerson of each type per day and it worked fine. I consider it essential to make each person an instance itself, considering they have to make pretty complex decisions, but I don't know how to make it work.

The game crashes specifically when I click on a button to change room. All of the objects are persistent.

\$\endgroup\$
2
\$\begingroup\$

GM:S is generally able to deal with as many instances as your machine is capable of handling, both in memory and CPU usage; every engine limitation is bonded to the machine the program is running on most of the times. Nowadays many games need to spawn a lot of instances simultaneously, and you can hear of projects displaying thousands of instances at once such as this one talked about on Reddit. In my experience, GM games usually crash because of code errors/exceptions, or memory/stack overflows, rarely because of instances number.

If your game crashes when you move to another room, you must be sure the transition doesn't trigger instance spawning over and over: you would be creating hundreds of instances without noticing, and that would cause memory to grow up until the application crashes; even worse, if object spawning happens inside a bad-formatted loop statement it may be mistakenly spawning objects without stopping, thus causing an infinite loop in your code leading the application to crashing.

Solutions to such problems include reviewing your code about checking the number of maximum instances you want to be in the game at once: you may think your code is bulletproof and not more than number_a_day oPerson objects will be spawned in your room; but if the spawning script is called more often that planned, it will result in uncontrolled growth of instance number in your game.

You could implement a slot system for the oManager object, which is given a maximum size and spawns a oPerson only if there's enough room in this variable (an array, a ds_map, or whatever you like to use). No objects are allowed to be spawned if it's full, and its size can be computed knowing the value of number_a_day or a larger value if you want to have room for extra instances. Recommendation is having an upper bound value to limit how many instances are moving around in your room.

EDIT
Persistent objects in GM may cause troubles as well. If you need to move to another room but getting back to the previous one having objects in the same state they were before leaving, you want to use persistent rooms.

This way objects aren't persistent anymore (and they will not be carried along when changing room), but anytime you get back to such persistent room everything will be in the same position and doing the same things they were doing before leaving.

Also there's no trouble for resetting a persistent room. User arirish shows a simple snippet in this GM:S forum discussion that allows a persistent room to return to its original state (thus, as it was when the game started).

This solution shall work for you, as persistent instances could cause the game to crash when moved to a different room (due to persistence) than the one they were supposed to move around.

\$\endgroup\$
  • \$\begingroup\$ Hi thank you for your comment. My set up currently works like this: the oManager object has a user_event. Every game day, this user_event would spawn hundreds of oPerson objects(symbolize the customer entering the station). In the mean time, after every game day a portion of oPerson instances will be destroyed (symbolize the customer leaving the station). A portion of the oPerson will maker the decision to go from one module to the other. Either way, on the frame which this user_event is triggered, many calculation are made at the same time, the fps spikes down to <200. \$\endgroup\$ – danielfang Sep 3 '18 at 21:37
  • \$\begingroup\$ Also the error message after the crash is: X://windows/Runner.exe exited with non-zero status (-1073741819) FAILED: Run Program Complete \$\endgroup\$ – danielfang Sep 3 '18 at 21:45
  • \$\begingroup\$ Mmh, check the following: you're playing too many sounds, and they're loaded in memory instead of streamed (memory limit); somewhere in your code you're trying to write/read beyond the size limit of some arrays (buffer overflow), or you're not properly deallocating possible dynamic resources (data structures, surfaces...) that cumulate and may cause a memory leak, and then memory limit is reached. To properly solve this problem, try to play the game with low number of oPersons and iterate through a couple of days, and debug run the game to keep a look on key variables and CPU usage. \$\endgroup\$ – liggiorgio Sep 3 '18 at 23:14
0
\$\begingroup\$

Is this code in a step event? And what do you mean by "crash", you get any error or the game just freezes?

Instance numbers in GM:S don't matter as much as the code that your instances have. Having a huge number of instances that have complex codes each can cause major slowdown (and you can follow that with show_debug_overlay(), as you did) but since you said the game instantly crashes, I'm guessing you are spawning too many instances at once, and GM:S thinks you are on an infinite loop and the game freezes (that, or you are actually spawning hundreds in a single step which is not good).

You didn't show what global.trader_modifier and global.tourist_modifier, etc are, so I'm not exactly sure how many of these instances you are spawning, but either way if this code is in a step event this code is just not viable, since you are at the very least spawning 31 passerby's per step which in a 30 room_speed game is 930 instances per second, and if this is in a create event, again, GM:S might consider this an infinite loop or its just too much.

I'm not too sure how you want your game to work, but either way spawning instances more smoothly throughout your game day would probably fix the issue, and in regards to how many of these instances you can spawn, that comes down to how complex their code is. You can check how many microseconds its taking to complete the code in your instances using get_timer() at the beginning of the code and storing it in a variable (like var t = get_timer()), and at the end of the code do show_debug_message("Code timer: " + string(get_timer()-t)).

\$\endgroup\$
  • \$\begingroup\$ Hi thank you for your comment. My set up currently works like this: the oManager object has a user_event. Every game day, this user_event would spawn hundreds of oPerson objects(symbolize the customer entering the station). In the mean time, after every game day a portion of oPerson instances will be destroyed (symbolize the customer leaving the station). A portion of the oPerson will maker the decision to go from one module to the other. Either way, on the frame which this user_event is triggered, many calculation are made at the same time, the fps spikes down to <200. \$\endgroup\$ – danielfang Sep 3 '18 at 21:37
  • \$\begingroup\$ Also the error message after the crash is: X://windows/Runner.exe exited with non-zero status (-1073741819) FAILED: Run Program Complete \$\endgroup\$ – danielfang Sep 3 '18 at 21:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.