简体   繁体   中英

How to Handle A Large Amount of Objects

I have a question about how to handle a very large number of objects to increase performance. I'm creating a 2D game with infinite block-like terrain, and obviously this is going to come with some performance issues.

The way I've come up with is to see if the player's X value has reached a multiple of 1000, and then I take every single block that is already in a save file or in the game world, and save it to the file. Afterwards, I destroy each block in the game world. After that, I loop through every block saved in the file and test if it's within a certain radius. If it is, I create that block.

However, I'm not even sure this is efficient at all. Every time I reach a multiple of 1000, the game freezes for a second or two, and after adding some print statements, it seems the majority of the time is spent reading the file. Is there a better way to handle this that I'm missing?

I'm actually working on such a game myself, so my approach may differ from what's best for you.

I personally use one of Google's Guava caches , with a removal listener. When a object is removed for any reason other than my removing it manually, I write it to disk. An example would be:

LoadingCache<Position2D, BlockOfTiles> graphs = CacheBuilder.newBuilder()
   .maximumSize(10000)
   .expireAfterWrite(10, TimeUnit.MINUTES)
   .removalListener(new MyTileMapListener())
   .build(
       new CacheLoader<Position2D, BlockOfTiles {
         public Graph load(Key key) throws AnyException {
           return loadFromDisk(key);
         }
       });

MyTileMapListner might look something like this:

private class MyTileMapListener implements RemovalListener<Position2D, MyBlockOfTiles>{
    @Override
    onRemoval(RemovalNotification<K,V> notification){
        if(notification.getCause()==RemovalCause.EXPLICIT) return;
        writeToDisk(notification.getKey(), notification.getValue());
    }
}

Currently, I'm able to keep 30K objects nicely loaded, in spite of their having large int[][][] arrays as fields.

A word of caution: The caches create threads internally. Make sure to use at least basic synchronization to keep the removal listener from interfering with your main thread when trying to write. Something as simple as synchronized( someCommonObject ){ // read or write } would work, and would be fairly idiomatic if the common object is your file output stream or something. Databases like LevelDB usually handle this for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM