Resizing game objects and components arrays

Started by
7 comments, last by crancran 10 years, 7 months ago

Hello,

My engine uses a component based architecture where I have an array of GameObjects and a number of other arrays each storing a type of component.

Something like this:

struct GameObject
{
    //indices to each of the game object components (-1 if component isnt used)
    int components[NUM_COMPONENTS];
};
 
GameObject*            gameObjects;
PositionComponent* positions;
ModelComponent*    models;
 

In order to implement Level Streaming I load the level file (actually it's a world section for an open world game) in a different thread (core) and I need to resize each (or some, depending on the game objects of the level being loaded) of the arrays above to be able to store the new level objects.

Since the loading is done in a different thread I need some kind of synchronization with the main thread. But simply putting the main thread on hold while the new larger arrays are allocated and the memory from the old ones is copied causes the game to freeze for around second.

Any ideas on how to make it more efficient like distributing the time across a few frames or something?

Thanks!

Advertisement

Since the loading is done in a different thread I need some kind of synchronization with the main thread. But simply putting the main thread on hold while the new larger arrays are allocated and the memory from the old ones is copied causes the game to freeze for around second.

Any ideas on how to make it more efficient like distributing the time across a few frames or something?

Thanks!

For streaming the only thing you can really do if an object isn't loaded is either refuse to draw it until it has finished loading in a secondary thread, or draw it with some kind of default model. It depends on the game of course but often if you're doing something like entering a new area and the nearby chunk of map hasn't loaded yet you may want to only draw the background and either some kind of manipulation of fog or to actually stop the game for a loading screen if it is of vital importance.

MMO's use the same kind of streaming but across the network, which is why objects tend to "pop up" after moving for awhile and the game may freeze or fade if you do something like teleport between areas because the client halts itself until it has at least the immediate surrounding data loaded, it's rather game by game in how you handle it. But the use of a secondary thread tends to be pretty much required. Using only one thread would simply cause stuttering each time you loaded an object even if you spaced them apart somehow.

The freeze isn't caused by reaching a zone of the map whose data hasn't finished loading yet.

It happens when player is still in zone "A" and loading of zone "B" begins. Since zone "A" only contains say 1000 objects the GameObjects array can hold 1000 objects, but in order to store the zone "B" objects the GameObjects array must resize which requires memory allocation and copying of the old data to the new array which causes the freeze since the game cant update while the data is being copied.


But simply putting the main thread on hold while the new larger arrays are allocated and the memory from the old ones is copied causes the game to freeze for around second.

Any ideas on how to make it more efficient like distributing the time across a few frames or something?

your streaming is not sufficiently preemptive. its should always complete background streaming before an asset is needed. if loading a world section all at once slows down the game too much, you'll need to start loading sooner, and spread it out over a longer period of time (multiple frames).

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

The freeze isn't caused by reaching a zone of the map whose data hasn't finished loading yet.

It happens when player is still in zone "A" and loading of zone "B" begins. Since zone "A" only contains say 1000 objects the GameObjects array can hold 1000 objects, but in order to store the zone "B" objects the GameObjects array must resize which requires memory allocation and copying of the old data to the new array which causes the freeze since the game cant update while the data is being copied.

fundamental design flaw there.

actually perhaps more than one.

may not be that hard to fix though.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php


But simply putting the main thread on hold while the new larger arrays are allocated and the memory from the old ones is copied causes the game to freeze for around second.

Streaming assets shouldn't have to be synchronized as long as each loader can work in its own segment of heap memory. The only synchronization that's needed is when pointers to the new data are added to the global pool of GameObjects*. Resizing even a large array of pointers (or use a std::queue) shouldn't have to cause any noticeable stalls.



Use a two dimensional array to store your objects. Essentially it looks like this:
Object_array [CURRENT_LEVEL] = all objects in current area
Object_array[NEXT_LEVEL] = all objects in next area

You can then do a swap to change CURRENT and NEXT when needed.

If reallocating and copying 2000 objects (pointers?) causes a one second freeze something else must be off.

Why not consider using a grid structure where game objects are stored based on their two dimensional position in the map?

Online MMOs like WoW break their entire map system into a grid structure. At a high level, the map is broken into lets say a 64x64 grid of large tiles that are further subdivided into smaller cells. This type of system lends itself well to querying for nearby objects, players, and entities for deciding who should receive chat bubbles as well as what should be streamed from server to client and what should be drawn on the screen beyond the terrain/skybox/weather.

In this case, you shouldn't have to worry about copying any information because what the player sees should be the contents of their current 2D cell position and perhaps the contents of the nearby 8 cells that surround their current cell. This way when the camera gets too far from a particular cell, you know precisely what game objects to remove and unaffected cells that should remain in view are untouched. It also allows you to forecast based on trajectory and speed which cells should start their preloading steps before the player arrives too closely to avoid pops of new entities, models, and characters while moving through the game world -- thus making a more fluid experience.

This topic is closed to new replies.

Advertisement