Making an Asynchronous Turn-based Game in Unity, Part II
Now that I have a basic prototype that adheres to the plan outlined in Part I-A, it’s time to build a server to support this game.
A longstanding (and totally hilarious) joke of mine is that I’ll play any game with a “Next Turn” button. As such, I plan to build a server that can support not just Clans but any future turn-based strategy games I build. Ideally I’d even love to open-source the server portion and allow other, less technical developers to start making this kind of game so that I can start playing them. =)
As such, here are my design goals for this:
- Support multiple different “Games”
- Support multiple users
- Support users having multiple “sessions” in multiple “games” (a session is basically an instance of a game. In other words, “Clans” would be the game while my 1v1 game against Gourmand would be a “session”)
- Support asynchronous chat within a session
So then, architecture: I initially plan to build this out as a rails-api application that primarily exists to persist game and chat state. The server will authenticate users and apps via OAuth2 password grants with each game as a different client.
While I’d be tempted to store game states on disk, serializing them to Postgres is the easiest solution for now since I plan to deploy to Heroku. I reserve the right to introduce a more sensible document store down the road however.
I haven’t found a way to incorporate Redis into this solution yet so let’s fix that. I’ll probably use it to store in-game chats as sorted sets per-user. Initially chat will only be global within a session so chats per-user is overkill. Eventually I’d love to support user-to-user chat as well though. Even if this turns out to be YAGNI1, it will be YAGNIBIIF?2
Next Time on the Making of “Clans”
This wraps up most of my planning materials. Once I have a Trello board for Clans, I’ll add a link to it here. (edit: here is that Trello board)
Next up, I’ll share what are becoming my current “best practices” for code organization in Unity. This has long been a sticking point for me as projects grow, but I’ve come across a style that seems to be the least painful.
You Ain’t Gonna Need It, http://en.wikipedia.org/wiki/You_aren’t_gonna_need_it (ignore anyone who says that stands for aren’t, by the way) ↩
You Ain’t Gonna Need It, But Isn’t It Fun? (citation needed) ↩
Making an Asynchronous Turn-based Game in Unity, Part I-A
The nice thing about working with a bunch of friendly and clever folk at Braintree is that they are always willing to brainstorm on better ways of building software. “Clans” is no exception, and within 20 minutes of posting Part I we1 had come up with a simpler way to build it.
In our last thrilling installment…
I left off in Part I talking about running Unity on the server. It consisted of two parts:
- Clients (our players) submit orders to the server that represent what they wanted to do on their turn.
- When the server has all orders for all players, it processes those orders on the server and sends back to clients the new game state that results from it.
Turns out that Step #2 is overkill2. Instead, once we have all players’ orders, we just have to send back to each client that collection of all players’ orders and let each client simulate what happened. As long as the simulation is deterministic, clients should end up with the same game state that the server would have generated. This avoids any kind of Unity/Mono running on the server at all.
This introduces the possibility of clients accidentally generating different ideas of the “current state” of the game and getting out-of-sync from one another. This is hardly a novel problem or indeed solution. The original Warcraft used a similar scheme in multiplayer albeit to solve very different problems than what I’m solving. There is a fascinating analysis of the Warcraft out-of-sync problem and its solution by one of Warcraft’s creators, Patrick Wyatt.
My solution will be a slight variation on the first step above. When clients send the server their orders, they’ll also send their understanding of the current game state. Specifically, each client will serialize the current state of the game as they understand it and produce an MD5 sum of the result. If any client sends an MD5 sum that differs from the others, the game is out-of-sync and is dealt with3.
The New Plan 4
- Clients (our players) submit orders to the server that represent what they want to do on their turn. In addition they submit an MD5 checksum of the current game state.
- When the server has all orders for all players, it verifies all clients had the same game state. It then sends back to clients all other clients’ orders.
- Each client verifies and simulates orders on their own to determine the next game state.
Next Time, on “Clans!”
Scott outlines how the server will work, something he promised to do in Part I! Enriquela discovers a terrible secret about sharks! Captain Boontz makes a decision that will change OMEGA GOGO SQUADRON forever.
TUNE IN NEXT TIME!
The server-side simulation approach has a couple of advantages still. In particular, it’s rather hard to cheat in that scenario. While “Clans” won’t have much hidden information, it will have some. A technically skilled cheater could reverse-engineer the client to provide omniscience within the state of the game. If Clans is popular enough to have that problem, I will be only too happy to revisit this scheme to simulate the game server-side and send partial state to clients. ↩
"Dealt with" is a euphemism for "game over." This won’t be a Civilization-style game where someone would lose 30 hours of gameplay if a game terminates. Additionally, this should be an extremely rare occurrence. You could send out the previous game state and keep the game "paused" until you get consistent states back from all clients, but I don’t care enough about this problem to bother. ↩
Until my clever coworkers come up with something else, that is. ↩
Making an Asynchronous Turn-based Game in Unity, Part I
In my previous post on my next game project “Clans” I outlined the kind of asynchronous turn-based strategy game I want to make. I didn’t discuss the implementation details though.
An asynchronous game implies there are persistent servers available to coordinate game state between players. I want to leave the option of an offline mode available, and I also need to make this easy to develop without having to run a server locally.
I experimented with a few options but it came down to two: build my game logic in a separate assembly and reference that from Unity, or take the compiled DLLs Unity creates of my custom code and find a way to run them without most of Unity.
Option 1: Separate Project
While building my game logic as a separate assembly is more logical and definitely cleaner, I ran into a few issues. While I don’t need most of what Unity provides in classes like MonoBehavior for my game logic, the utility classes around math and vectors would be a big help. Furthermore, Unity periodically likes to rebuild your solution files which forces me to periodically re-add my GameLogic project.
Option 2: Headless Unity
When you build & run your Unity game, Unity compiles all of the custom code you’ve written for your game into a DLL named “Assembly-
After I tracked down those DLLs though, I was able to make a simple command-line application that used those DLLs to process some simple game logic. I’ll have to be diligent in separating my logic code from anything that requires Unity’s “MonoBehavior” components as anything that references any of their event lifecycle hooks like Start() and Update() won’t work. This shouldn’t be a problem for turn-based strategy games, as they shouldn’t be making use of Unity’s game physics or other logical components for any important bits of game state.
In the next installment I’ll show how all of this is going to come together. I may even make a diagram! GET READY
Another Game in the Works: “Clans”
After a period of game-making hibernation, today I found the time to get back into shape. Previously I had teased about a strategy game called MUTANT OVERLORDS. As my design doc hit the 4,500th word for that game, I realized that perhaps it was beyond the scope of my current skills. I’d like to tackle it someday, but it’s prudent to start on something less ambitious.
"Clans" (very much a working title) is a simple asynchronous turn-based strategy game of hidden information. Drawing inspiration from the board game Sekigahara, victory in “Clans” will be achieved by surprising your enemy by your unit composition and choosing the right time to play “tactics” cards that can change the nature of battles:
Armies are composed of stacks of units and used to take key parts of a point-to-point map. On your turn, you’ll queue up movement orders for your armies. When you opponent has done the same, the orders will be resolved simultaneously.
Choosing and ordering the individual units of an army is the key mechanic of “Clans.” While your opponent will see your armies and the number of units in them at all times, they won’t know the composition of your army. Perhaps you’ve filled it with a number of cheap, fast units to give the impression of strength where there is none. Perhaps you have an elite few heavy hitters. Perhaps you have a mix:
Each type of unit will have an ability it grants to its army when it is the topmost “lead” unit in the army. In the above screenshot, a “shield” unit is atop the army which makes it both harder to kill and harder to move.
I have some further ideas on how this mechanic will work to offset the obvious “kitchen sink” army composition strategy that this otherwise lends itself to. I don’t want to say too much more until I have more than a simple mockup though.
Reach out with any questions and stay tuned for future updates!
"Meditation brings wisdom; lack of meditation leaves ignorance. Know well what leads you forward and what holds you back." - Gautama Buddha
5-Year Old Wants To Be A Tractor When She Grows Up
FLASH BOYS, Employment Agreements, and Market Fairness
Michael Lewis’ new book on high-frequency trading, FLASH BOYS, is stunning. While free markets are based on the relatively fair flow of information between players, FLASH BOYS shows how profitable it can be to obfuscate and restrain that information.
Lewis describes one small group’s efforts to restore the fairness of information in the market. It’s a story that couldn’t happen in the traditional web of non-solicits and non-competes that decorate contracts like ornaments at Christmas. Thankfully the major actors in FLASH BOYS weren’t bound by them and worked to improve the market. Otherwise it would have been a short book - a few key people had an idea on how to restore fairness to the market but couldn’t.
These other, more common restrictions on the free flow of information within a market trouble me1. I understand and respect intellectual property but I cry foul when companies claim IP within their employees. It clearly hurts the market, but also wreaks havoc on the individuals caught up in it as well.
If a company can’t lazily leverage legalese for retention, they are forced to invest in their employees and in their culture. If each employee feels valued and empowered there is no incentive to leave the company to follow ideas and passions. Employers must make it absurd to consider leaving to compete against them. It’s a scenario where all parties benefit but it isn’t easy.
If you get the chance, FLASH BOYS is filled with insights like these and I can’t recommend it enough. A number of ideas have stuck with me from it and I continue to mull them over. You’re likely to see more of them within this space.
particularly as I am currently bound by them. ↩
No Conclusion on No-Hire Lawsuit?
The New York Times is reporting this morning that a settlement is close in the class-action lawsuit brought against Google, Apple, Intel, and Adobe for their discriminatory and illegal no-hire, no-solicit agreements amongst one another.
For those who haven’t been watching this case, those four companies (and previously also Intuit, Lucasfilm, Pixar, and eBay, who have since settled for pittances) have been accused by potential employees as having an agreement not to hire employees from the other companies. The proceedings have already led to the discovery of numerous emails documenting the process, so I use “accused” pretty loosely here.
I’d be very sorry to see this settled rather than set a precedent. I am fanatic about retaining employee mobility as society transitions further towards employees as disposable, transient resources. With the high-profile companies involved, this was a fantastic opportunity to clearly make this an illegal act for others considering the same.
This isn’t just theoretical either - I was nearly the victim of such an agreement back in 2009. A number of CEOs from bootstrapped Chicago companies and consultancies formed a networking group. The cost to entry was, amongst other things, an agreement not to solicit employees from any of the members of this group. When I reached out to Obtiva to work there in 2009, I was unlucky enough to work for one of the other members of this group.
I may have been rejected outright if it weren’t for the fact I found out about this and had a very lively conversation with my soon-to-be former employer. I was one of the fortunate ones though - I learned this was happening. Usually this unfair labor practice manifests itself in the form rejection letter, the unanswered email, or the strangely reticent recruiter. This isn’t even to mention the other victims like the Google recruiter that Steve Jobs had fired for daring to do his job in the face of these illegal agreements.
I’ll be crossing my fingers that this article is inaccurate, but I suspect not with the number of other companies that have already settled similar claims. It’s a shame - when a case like this settles for such small amounts, the only legal precedent becomes “don’t get caught.”
(On a side note - The New York Times has been fantastic in covering this case - virtually every meaningful update has been on page one of either their National or Business section. If you care about these things too, you might consider throwing them a few nickels)
It pleases me immensely that GATTACA has aged like a fine wine.