question

cootejames avatar image
cootejames asked

PlayFab for a persistent Business SIm

Hi,

I'm making a business sim in Unity3d, with a persistent world that all players are a part of. I'm trying to work out which bits of the game I can do using PlayFab, and open to suggestions on what to use for the things PlayFab can't do.

Specifically, the game has the following requirements:

1. Base Building Anywhere

The game is set in space, with all the basic data about star systems, planets etc stored locally, and this data never changes.

Players can build mines, factories etc on planets, but each planet has a limited number of build positions, and only one player / one building can occupy any one position.

When a player zooms in to view a planet, they need to be able to see what buildings other players have built on that planet (though not the details of the building). So that they know which positions are free to build on.

2. Inventory Anywhere

Players can mine minerals on planets and manufacture consumer goods from those minerals. But the minerals and goods are only available on the planet where they are made. So the player needs to be able to have lots of stockpiles of stuff all over the place.

3. DHL in Space

Players can send their minerals/goods between planets via a NPC courrier service. They say what they want transported and where they want it transported to. Then their stuff takes x days to get delivered, in which time they can't touch it.

4. Want to Buy/Sell

Players can sell their minerals/goods to each other by placing "want to buy" and "want to sell" ads. Or by buying/selling to those ads.

So players need to be able to see others' ads. Plus there needs to be a system to resolve transactions, so the buyer gets their minerals/goods added to their inventory on whatever planet the ad was placed at. And the seller get their money. And finally, the ad needs to be updated, in case it is only partially filled: E.g. "I want to buy 10 crystals". Player B sells 2 crystals. The ad becomes "I want to buy 8 crystals" (Basically the same as Eve-online markets, for anyone who's ever played that game).

5. Running Costs

Player's buildings all have running costs. So every hour, X soft-currency credits are deducted from their balance. If the balance goes negative, they go "bankrupt", meaning all their buildings are disabled and can't be used (but also don't incur costs). Players can scrap (destroy) buildings for credits, and sell minerals/goods to try and get their balance positive. Then spend to unlock remaining buildings.

Players get Y days to get their balance positive, before buildings are automatically scrapped one-by-one until none are left. (So if you don't play for 6 months, when you return, you'll have no buildings left, but you will have a small stack of cash from your scrapped buildings).

Players also get a limited number of "vacation days" per year when they can set all their buildings to be disabled, and so not incur costs.

--

I'd guess 5. can be done using a server side script? My worry is making it efficient / not taking up too many server resources doing it.

I also figure 2. and 3. can be done by simply adding some extra data to the inventory items players own. E.g. a position / address field: "sector7, star1928, planet8". Just need to know if this idea makes sense in the context of how PlayFab stores data and the client accesses it.

For 1. (build anywhere), a building could similarly be in the player's inventory and have an address field. Just a case of how to let other players search by address. Is this possible in PlayFab or if not, open to ideas on what to use instead.

For 4. (buy/sell), I noticed PlayFab has an API to allow players to trade, but seems like it's more based on helping your friend by giving them an item, rather than what I'm after? Again, on the hunt for solutions to use if, as I suspect, PlayFab isn't quite appropriate to use in this case.

As well, if anyone has suggestions on how to reduce traffic/server load with these feature requirements, would be interested to hear. With all of these things, there'd be limits, so players can't just build 10,000 mines or place 5000 want-to-buy ads for 1 crystal each. Equally, I assume PlayFab has some clever caching stuff going on in the background?

Thanks
James Coote

apisTrading
1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Brian Jordan avatar image Brian Jordan commented ·

Re: #5, one handy trick to structuring building-timer-based values efficiently is to store "start times" and "start amount"s (rather than "expire times" and "current amount") and update those only when changes occur. Then in your "get current amount" helpers, derive the current amount from those starting parameters.

0 Likes 0 ·
brendan avatar image
brendan answered

So, the essential problem is that what you want to build is an MMO. Data systems are discussed in a number of posts in the forums (such as this one https://community.playfab.com/questions/18236/possible-to-query-all-users-for-the-same-character.html), but in short:

There are two basic types of data systems:

1. Title-level data, that is sharded and (to your point) cached. That's data that is updated rarely, by the developer or publisher, and is available to all players in the game. The point here is that the data must be sharded and cached so that it can be queried by all players in the game.

2. Player-level data, this is not sharded or cached, and so can only be accessed by a very small number of users at a time. That's all our player data and shared group data systems. Because they need to have high levels of consistency, they cannot be sharded or cached. And because they aren't, if thousands (or millions) of requests came in for the same data all at once, that would cause a massive bottleneck.

In MMOs, the data that can be updated by all players and is available to all players is stored in in-memory data systems, on the servers that are running the gameplay. That way, the data can be served to tons of players in very narrow windows, and many updates can be queued and processed quickly. You cannot do that with a data table system that isn't in-memory, since the latency time would mean that when you try to go to scale, your system is guaranteed to fail.

Now, what you could do would be to have players have bases that they create which are not part of a globally-consistent data set, and then have players challenge each other to take possession of that "property" by having them to async matches using leaderboard lookups (GetLeaderboardAroundPlayer is a common example). Alternately, you could run custom game servers that maintain state information about "shards" of the game that players can join, so that you have a way to maintain an in-memory state of properties that players own, though if you want to go the latter route, I'd recommend working on an external hosting system. The PlayFab custom game server hosting system is really designed for short-lived dedicated servers, such as those you see in shooter games.

1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

cootejames avatar image cootejames commented ·

To add more info, the game universe is v. big: 10k stars, 3 to 9 planets per star. 842 building positions per planet. Conversely, placing a building is quite a rare event. Maybe once per week per player.

Based on that, I've a possible solution:

1. If Player A is 1st to build a building on a planet, they become the "owner" of that planet. So 842 bytes of their user data is used to store which positions on the planet are already occupied.

2. The "new planet owner" statistic for Player A is set to the ID number of the planet.

3. Every hour (or day or whatever), the "new planet owner" leaderboard gets reset, and all players that were in that leaderboard get added via a cloud script to the title-level data. So the title-level data now holds a map of planet IDs to player IDs.

4. Player B wants to build a building. They start by looking for the planet owner in the cached Title-level data. Failing that, Player B looks in the "new planet owner" leaderboard.


5. On finding an owner, Player B looks up the owner's user data to see what positions are free. Then, on building, Player B updates the owner to say a position is now occupied.

6. If there is no owner, Player B becomes the new owner.

0 Likes 0 ·
brendan avatar image
brendan answered

Moving this out to another answer, since it needs more text than will fit in a comment.

No, that's not going to work for any non-trivial number of users, but I do have some recommendations (really, one main one):

First, Cloud Script is designed for simple, lightweight operations. Iterating across an entire leaderboard to write that to Title Data would fail, as it would require too many API calls as well as too much CPU time (both of which are strictly limited in Cloud Script calls). Now, we are going to be providing another scripting system that'll allow for longer call times in the near future, but even then, if the title were to get (even marginally) popular, this is very likely to be too CPU intensive. You'd be far better off managing this data using a custom game server, so that you can maintain the state of your "universe" there, and periodically update backend data with the latest info.

Second, the existing Player Data system would have the problem that if two players attempt to update the same data at the same time, only the last update call is going to "win", making you lose data frequently - especially if your design allows people to choose planets, since that would inevitably result in many players trying to target the same data. Our newer data model, which we're releasing now, allows for blocking updates, so that you can ensure people can't stomp each other, but if you have more than a few users targeting the same data, that's still not going to work. So again, you really need to have this data living in-memory on a custom game server, so that you can manage the interactions of the players with the planets.

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.