Best practice to store data that will be used more often

I store some data like achievement structure
which contains achievement id , points to unlock and so on

I store it as json string

var achievementStructureJson string

the first time the player connect will get achievementStructureJson, if doesn’t exist in his device using RPC

is this how things usually done or there is a better approach

Also, what about game configurations that may change

I am using Go

I set up an achievement system using GameSparks for a Ziosk contract a few years ago. What you have sounds like a good start. I would add a versioning check as well, upon connection, verify local version vs back end version. If version of back end is greater, re-pull the data and store it locally.

I like the back end driven approach for achievements, the only caveat is to create tracking ‘events’ client side for all potential back end achievements, since you can’t change those without a new client build.

For an example, let’s say there is an achievement for killing 10 rats. Client side would have some kind of an event that is raised when an enemy is killed, and the type. Perhaps there is no achievement for this, or perhaps they need to acquire a ‘quest’ before tracking becomes active… all of this depends on your goals.

When your achievement json is loaded at the start/connection, your client will probably also wants an ‘active achievements’ per-client. If there is no active achievement for killing a rat, then there is no handler for it. If there is an active quest or achievement, a handler will respond to the kill, and increment the associated achievements for that type.

For example, you may have 2-3 achievements for killing a rat. One could be a ‘kill 10 rats’ quest. Another could be just global ‘kill rat’ counts, another could be a ‘kill rodent family’ count, etc. In any case, if something is listening for this ‘killevent’ of type ‘rat’. All of their handlers will update the client data for the achievements (local or database). If the achievement is complete, you’ll remove the handler for that achievement, and reward the prize. The prize could just be the badge, or an item, etc. It is all up to you.

Hopefully I didn’t go overboard trying to explain… so now let’s say you never created an event for ‘kill’ and of type ‘rat’. Or handlers to do something with that event. None of the back end achievements or handlers would work, and you would need to redistribute a new client with that event, for the achievement system to use.

You may want three different structures: achievement definitions, active achievements, and completed achievements.

Hey @Mohammed, it depends how you are using the achievement data, but in general, loading data onto a fresh device for a user with an existing account is entirely reasonable and necessary.

In terms of changing game configurations – can you give an example?

@Bunzaga thank you for your replay
The details you put are very help full, I actually already implemented check achievement version but I did not want to put unrelated details on the question.
What I currently do is I have is a JSON structure for achievements
each achievement will have some details like reward you get , how many points to achieve it and so on.

The JSON structure for achievements will be saved on Nakama storage and will be loaded on startup
I have an RPC to modify the achievements (add new achievement, edit rewards and so on)

Adding new achievement is not a problem, as the client can designed to handle it.
As I already have a set of all possible rewards.

My issue is when I load the json first time should I put it as GLOBAL variable, knowing it may be updated but rarely and only by server side (… i can make maintenance break like many games does)

What i want to say
is using global variable in go is okay if not constant and if only for read but modified by server side

Hey @lugehorsam

but in general, loading data onto a fresh device for a user with an existing account is entirely reasonable and necessary.

great, where this data should be loaded from

  1. Reading Nakama storage?
  2. Global variable
  3. or something else

knowing this data is common for all players,
also the data is read-only most of time … except for server side update

Hey @Mohammed, yes I’d use Nakama’s storage directly rather than placing the data in a global variable. There are global readonly permissions allowed in the storage engine. Then I’d just retrieve storage using the APIs provided by our sdks.

@lugehorsam,

But the data will be used by the server to check player achievements and requested almost non stop by player’s.

So I am worried it will not be efficient to read from storage every time while i could used the same data while it is in memory for all players.

Do you recommend to cache this data in RAM?

@Mohammed you don’t need to constantly request achievement data for all the players. You should cache achievement data on the client and check at some periodic interval such as app start for new achievement data on the server.

1 Like