How to Detect if an item exists in memory?

I’m self-taught so I’m a little lacking in expertise. I know that Godot doesn’t have the traditional try/catch so I’m trying to figure out how to detect this error.

My Android game has a a memory file, it works perfectly. Some example variables:

game_memory.total_games_played:int = 0
game_memory.total_games_won:int = 0
game_memory.high_score:int = 0

So now it has come to the point I wish to add a new variable to memory, for example:

game_memory.best_time:int

For the people who have already have the game on their phones, the file saved to memory will not have a “best_time” variable in the memory file, so if I push out a new game update that attempts to access such variable it will crash/ANR the game.

During testing I get the error when I attempt to access a new best_time variable:

Invalid access to property or key 'best_time' on base object type Resource(Memory)

OK, this all makes sense, I expect this. My issue is how can I test that the property of key exists so I run code to create a new memory file and use it to save over the old one? I really don’t want to create file and then have to manage 2 files in my game - that seems like bad coding.

I have tried potential solutions such as:

if game_memory.best_time == null
if is_instance_valid(game_memory.best_time)

But none of these work. I just need a way to do something like this:

try:

     var test:int = game_memory.best_time

catch:
 
    func_to_update_memory_file_to_include_new_variables()

Can something like this be achieved in Godot? Thanks

You should just be able to use game_memory.has(&"best_time")

Unfortunately I get this error:

Invalid call. Nonexistent function 'has' in base 'Resource (Memory)'.

Turn it into a dictionary and has() will work.

1 Like

OK…I would have to convert the current Memory file from this:

game_memory.total_games_played:int = 0
game_memory.total_games_won:int = 0
game_memory.high_score:int = 0

to this:

@export memory_dictionary = {

       "total_games_played" : 0
       "total_games_won" : 0
       "high_score" : 0
}

to get the “has” call to work. But this loops me back to the same problem - or creates a different/ similar problem. Now I need the same thing, a try/catch code snippet so that when the player opens the game - is the saved memory the updated dictionary version or the original version.

You’re trying to solve a problem that doesn’t exist.

Again, using the Dictionary solves this problem out of the gate. Take a look at the Save/Load Example in the official documentation. By saving a Dictionary, you can just load the value and if it doesn’t exist you can default to a zero.

If you don’t want to write all that code, I wrote a plugin for it called Disk. Then all you have to do is add your Resource (or the Node containing it) to the Persist group. Then pass the Dictionary through a custom save_game() function, and load whatever data exists in a custom load_game() function. Any new fields would just stay at their default value, old values would load and on next save, all values would be saved. (If you’re interested in using it and the documentation isn’t enough I can write you some example code here.)

Dictionaries are great for this because of the get_or_add() method. If it’s there, it’ll retrieve the value. If not, it will insert the default value specified and return it.

So you would do:

var best_time: int = memory_dictionary.get_or_add("best_time", 0)
1 Like

Since the Resource class inherits from Object you can use the Object method get() to determine if your custom property exists.

if game_memory.get("best_time") == null: 
    print("this property does not exist")
1 Like