0
\$\begingroup\$

We are creating a RTS mobile game and we face some problem dealing with updating a lot of object in db too often.

Our game is a RTS in which players can attack enemies cities an take them. The world is procedural and potentially infinite, when players spawn we extend the map if needed (no city left). Our map is reset every month. Each city hold an army and produce an amount of army based on the city level. We also have some items that the player can equip and unequip. Those items may give some army production bonus.

At the biginning most of players had around 30-50 cities. But since the player number increased some players now have over 1000 cities.

Our data structure look like this (mongodb)

City:
- id (ObjectId)
- location [x(int), y(int)]
- level (int)
- armyAmount (double)
- lastArmyUpdate (Date)
- armyProductionMultiplier (double)

Player:
- id (ObjectId)
- Name (string)
- Items [key (int), equiped(bool)]
- Cities [cityId (ObjectId)]

When a city is attacked we refresh the army based on the last update and the city production.

army = oldArmy + cityProduction*armyProductionMultiplier*TimeSinceLastUpdate

It works well as we only update the value when needed.

But when players equip an item that give them army production bonus we need to update the multiplier on each city the player own and to update the army amount considering the old multiplier before applying the new one. If the player only change his item once per day it's ok but if he swap every minutes it will make a lot of database query and waste a lot of cpu time.

We could set a timer between items swap but it would be frustrating for the player.

QUESTION: Is there a db pattern or a better way to reduce the cost of the item swapping.

Thank you!

\$\endgroup\$
  • \$\begingroup\$ Why is a database involved here at all? Most real time strategy games shouldn’t have to write to disk at all, let alone to a complicated to use database server, unless you’re saving the game. \$\endgroup\$ – Joe Feb 24 at 15:01
  • \$\begingroup\$ I updated the question, our game is played for a whole month. We cannot keep the data in ram for such a long time and we need to keep it in db. \$\endgroup\$ – Cyrius Feb 24 at 16:57
3
\$\begingroup\$

Have you profiled to be sure what the actual problem is? You might find that there is something as "simple" as a Mongo configuration causing poor performance. There's also of course questions of whether Mongo is the best storage to use for something with high-frequency writes. I know RDBMS isn't hip these days, but it's a lot easier to optimize and scale for these kinds of use cases, and RDBMS systems like Postgres are doing a pretty good job of obviating Mongo by adding mixed-mode document storage while still allowing relational indices and keys.

However, in terms of your design, this bit in particular stands out to me:

But when players equip an item that give them army production bonus we need to update the multiplier on each city the player own and to update the army amount considering the old multiplier before applying the new one.

You're imposing N writes for 1 operation, where N is the number of cities. This is clearly going to be a scaling problem. For 1 operation (equip item), there should ideally be only 1 write.

Perhaps instead of caching this production bonus, calculate it on demand from the player's inventory when needed. This would of course shift some computational overhead into (potentially high-frequency) reads, but that is sometimes worth it compared to writes (esp. as reads can be distributed in ways that writes cannot).

Typically, you want to write as rarely as possible, and you don't want to write to multiple records for a single change (e.g., equipping an item should just write the equipment state and not need to modify a bunch of city records). If there's something you can calculate on demand, prefer that over a write. You can still cache these values in a more transient storage (e.d. Reddis, or in memory, or in a local Mongo "shard") if they're used often.

From a game design perspective, hiding technical latencies is one of the reasons games introduce cooldowns, animations, and other delays. In real-time games, you'll see these techniques used to mask network latency, A* path-finding queries, "slow" server tick rates, level loading/streaming, and so on, though you might not even realize these techniques are in play if you're not really looking for them. :)

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.