Jump to content
  • Advertisement
Michael Aganier

Data access layer design for games

This topic is 409 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,

I'm trying to refactor my data access code so that it's as clean as possible. Though I'm not looking to use MVC pattern in my project, I still want my code to be well organised and as of right now, I can't help but feel like it could be quite better. For now, I want to concentrate on everything related to data access in my code.

In the MVC pattern, the business layer talks to the data access layer which talks to the data store. (skipping the presentation part)

  1. business talks to data access  (game init)
  2. data access talks to data store (repository request)
  3. data store returns query to data access (database fetch)
  4. data access builds object from query data (data mapping)
  5. data access returns built object to business (repository return)
  6. business works with object (gameplay)

Here is my current process:

  1. business talks to data store
  2. data store returns query to business
  3. business gives query data to data mapper
  4. data mapper returns built object to business
  5. business works with object (gameplay)

In a pseudo code example, this is how I would build an archer entity:

init () {
  	/* Step 1 + 2: business talks to data store and data store returns query data */
	XMLData archerXml = database.find_xml("entities/archer");
  	/* Step 3 + 4: business gives query data to data mapper data mapper returns built object to business */
	Entity archer = data_mapper.map_entity(archerXml);
  
	/* Step 5: work with object */
	allEntities.add(archer);
}

update () {
  	/* Step 5: work with object */
	for each (entity in allEntities) {
		entity.update();
	}
}

 

 

How do you handle data access in your games? Is there existing data access patterns for game programming?

Share this post


Link to post
Share on other sites
Advertisement

This depends on what you try to do. Going into UI development threre are several ways to do things "right" from coupling anything, MVC, MVVM or something that works like a Server/Client environment (your server does not now anything about the client while your client knows the server) against gameplay data access or asset management.

Game data access can be solved by a bunch of possibilities using events, using global static or singelton static management classes, closed or semi open systems or using an ECS (entity component system) like Unity 3D does. In general your game should be structured in systems that each has itself one single task to keep hold of. This may be rendering, AI or game logic. Then you need to have those systems provide as few as possible interaction capabilities to other code like query information needed about entities, physics events or material states always depending on your needs. The render system does not need to know current AI sates while AI maybe tell render system to play some animation.

But your problem seems like a resource loading issue. These loading operations should be done by the resource manager and/or in cooperation with a scene graph and you should tell your resource manager only to create an instance of your "Asset" archer or whatever. Resource manager then should handle loads itself and potential add the archer entity into a list of entities like a scene graph (or let the entity do this by itself when calling the constructor).

This is the only "general" advice that I could give you without an exact scenario what do you want to achieve and where/when do you intend to access it

Share this post


Link to post
Share on other sites

As Shaarigan has written above: "it depends". It is clearly not meaningful to try to solve all problems by fitting into a specific pattern. Instead a software, especially one as complex as a game engine, can only be written by using the particularly right tool for each of the manifold problems. So here are some common situations and possible solutions:

In the cross section of posts (and matching my personal opinion, so I may be biased on this), resource loading is a thing that involves approx. four instances which together define what I usually call the resource manager:
* the manager's frontend interface and processing logic (further called simply "frontend")
* a resource cache buried within the manager
* a resource loader buried within the manager
* a memory manager to deal with memory allocation (if you want to do this)

The concept is roughly so that clients send their request for a resource to the manager's frontend (they don't see anything else anyway). The frontend makes a look-up of the requested resource by calling the cache. On a hit the cache returns the requested resource and marks it being used one more time, and the frontend returns that object, of course. On a cache miss the frontend instructs the resource loader to create a new instance of the requested resource. The loader may be complex by itself, e.g. dealing with directories of resources, archives, overriding, ... but that is not of special interest here. Instead we just say that the resource frontend uses the loader frontend to cause a resource loading. However, the loader may use the memory management in case that we want to load resource considering their lifetime (e.g. the player avatar will be long lasting, other stuff exists for the entire lifetime of the level, and other stuff may be swapped out again when a memory budget gets exhausted. However, the loaded instance is then put into the cache and returned to the caller.

The above description shows a kind of access control: All things a client can do goes through an (more or less) narrow API regardless how complex the process in the background is. However, is a resource manager already business logic or still data store? IMO it is both: From the outside it looks like a data store, but from the inside it has some logic build in to help a fluent processing of the overall system.

Coming now to the second aspect of accessing data as shown in the OP: entity updates. First of, entities are not resources. Instead entities are runtime objects that use resources. E.g. an archer entity uses specific skeleton, mesh, texture, animation, AI resources, maybe even a specific entity template resource. That means w.r.t. separated concerns that something I will call the "entity manager" here is available. This thing is on a higher layer of abstraction, and as such it is allowed to use lower layers. Thinking of layers is another common way to architect software. It means that low level services are used by higher level services but not the other way around.

Having an foreach Entity::update() as such is IMO not possible in reality, because there is not such a thing like a single isolated update of each and every entity. The game loop is in fact a sequence of updates run by sub-systems, where each sub-system deals with a particular aspect (for example a particular component of an entity when thinking of ECS; you may want to read Jason Gregory's book chapter about updates, e.g. the excerpt here on gamasutra). It is not meaningful to move the first entity an then run a collision detection and correction, and then step over to the next entity and do the same. Furthermore, static objects do not even have a movement update. Or in other words: different entities have different needs. This leads to another IMO fundamental though: Each aspect should manage their data themselves (some exceptions may exist) and do this in a way that allows themselves to run smoothly. This allows to use data access patterns matching the particular needs of sub-systems, rather than to enforce sub-systems to access data in one globally provided way.

tl;dr: Discussing data access should be a topic done narrowed down to one or a few related use cases. Hopefully not just my 2 cents ;)

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!