As mentioned previously, I’ve started fleshing out the backend for the server that I’m looking to build for my ongoing experiments.
Let’s recap the key points:
The first 2 elements to our server design can be broken nicely into:
- Static Content (Metadata)
- Dynamic Content (Player data)
You can consider metadata to be anything static in your game that doesn’t change from player to player. This could be an inventory of all the weapons in your game, or a list of all the level names, all the dialog text in the game, and so on. I would highly recommend that you store all of this static information server-side so that it is easy modified and updated after launch. Yes all of it. I’m not kidding in the slightest. Every weapon, every item in your massive RPG, every character’s details, the story of your game. Store all of it on the server and query it dynamically (well, mostly dynamically, we’ll go through how we can cache this and allow offline play etc later). Yes I did say ‘offline play’ – almost nothing about what I’m proposing here would necessarily prevent offline play, but that’s up to you to decide for your particular title.
The dynamic content in your game is the player-specific user data that gets stored as they start the game and progress through the adventure. This could include their progression through the tech tree in your game, their inventory, unlocked levels, etc. It could also include a more complex save game system that stores microstates of each object in a scene if you like. All of this information gets pushed to the server and pulled down dynamically when the player first launches the game / effectively ‘syncing’ their game state. Every MMO that you have played does this kind of thing, and probably a number of other games that you have played in the past 3-5 years as well. Unfortunately not nearly enough do this kind of cloud-saving (in my opinion).
So now that we know what we are trying to do, let’s discuss a bit about how we might achieve this.
As a caveat, I’ll definitely say that my approach is likely going to be far from typical, however the underlying principles are based on many years of experience working with similar systems, both from the web-development standpoint as well as from the game development side of things. My career has floated almost equally on both sides of the fence. Years ago this seemed a bit strange to me, but they have effectively merged with this new approach, and I find the end-result so much easier to maintain.
My primary goal in this experiment is to reuse existing code and libraries where possible to maximize how much I can get done with the minimal amount of code. As a single-person (at the moment anyways) indie developer, there are far greater challenges and tasks on my plate than writing a full-fledged content management system to handle both the static and dynamic aspects of my project, and realistically, there is probably someone who has already written the majority of what I’m hoping to achieve already.
Before I dive into the particulars of the separate systems, lets take a look at a higher level set of functionality that I’m looking for with my Static AND Dynamic systems to see if there is a few common threads that might help me narrow down an approach.
- Runs on the standard LAMP stack (LAMP being Linux / Apache / MySQL / PHP, although the apache element might get swapped out with a more efficient web server before I’m done). This makes hosting & scaling the system a ‘known quantity’ that doesn’t require esoteric / specialized knowledge to achieve.
- Reuse / provide as much functionality out of the box without requiring a massive code rewrite or repurpose.
- Provides me with a web-based interface for editing the game data (either static metadata or player game data). For this reason alone, writing a custom PHP / MySQL app is less appealing. Building a nice easy to use interface for a database app can often take longer than the core functionality itself, so I’m hoping for an existing solution that will solve this problem.
- Be easily scaleable – either as an existing ‘appliance’ that I can plug into amazon or rightscale or something similarly easy to deploy into a cloud-based system. I don’t believe that cloud systems are the end-all-be-all for scaling an app, but they do provide a starting point for a solution, and having something that I can quickly deploy if need be is crucial. Last thing you want is for an app to become popular and not have a plan for scaling the app ;}
- Provide a JSON interface (or easy access to data so that I can build my custom JSON API for the server communication layer). I’ve been working with JSON based server API’s for the past year and have really enjoyed how easy they are to work with. This plus the fact that PHP has very powerful built-in support for JSON serialization and parsing gives me a head-start building the server communication layer. I’ll go into this probably next time as we get closer to the client / front end design.
That pretty much covers my high-level requirements for the system. Let’s dive into some details.
Static Content Management (Metadata)
For any game, there is a large amount of static content, what I’m dubbing Metadata, required for the game. Think of this as the look up values for everything from the number of levels in the game, how many enemies a particular wave should contain, details about how strong a particular enemy should be, all the way down to how many XP a particular game event should grant the player.
For a traditional single player game, this data was either hard-coded in the game code (or hopefully a text config file at a minimum). With tools like Unity, the metadata can be thought of as the public interface for your class that Unity exposes in the editor at design time. This isn’t necessarily a hard & fast rule, but it’s a good rough starting point for us to begin working from.
To provide a more specific example, let’s break down one potential class in our theoretical game and figure out what kind of metadata you might want to poll the server for.
Lets assume that our game has a variety of enemies that the player must fight. These enemies probably have Health, Movement speed, Damage (and/or Damage per Second), firing range, and other similar properties. These variables are a perfect candidate for grabbing from the server. If we have them hard-coded in the client, then after our game launches, we will never be able to update or modify these values without pushing out a new client update / patch. If our game isn’t perfectly balanced at launch (and let’s be honest, very few are), we will be stuck with these values until we can get an update / patch for our game out the door. However, if we are polling this metadata from the server at runtime, updating & modifying these values are all of a server-side tweak away. This is exactly the type of thing that every game should be looking into using.
This same method can be applied to just about every aspect of our game. What missions are available in our game, what enemies (and how many) get spawned for each level, etc can and should be retrieved from the server at runtime to allow for the maximum flexibility in our codebase.
Most programmers have heard of ‘data-driven design’. The traditional description of this is to separate the data that drives an application from the code / logic that makes things come to life. What this mean in many apps is having a local database
What I am expressing here is a relatively straightforward extension of this methodology.
Now that everyone understands this (hopefully) approach to the overall design to the client & server, next up we’ll start to design the json server api that we will be using to pass information back and forth and start building up our client/server communication stack. The fun begins ;}
Until next time…