0
Answered

Retrieve AoT dictionary from Bolt variable to script?

GhostAegis 2 years ago updated 2 years ago 6

I'm trying to retrieve an AoT Dictionary so that I can use it in a script, following the instructions in the API documentation. However, I get this error:

InvalidCastException: Cannot cast from source type to destination type.

This is the method I'm calling:

    void ReadBoltData(){

           dictionary = (Dictionary<string, bool[]>)Variables.Application.Get("progress");

    }

Where the variable dictionary exists in the scope of the entire script as:

public Dictionary<string, bool[]> dictionary;

I think I'm casting it correctly, but I've never tried to do it with a dictionary before. Am I missing something or is there something about the AoT Dictionaries that prevents this? 

What I'm trying to do is use application variables to store a whole bunch of progress-tracking dictionaries during runtime, for ease of access from all my Bolt macros. Then I could fetch and serialize those to a save file whenever I need to save, and vice-versa.

That being said, I'm stuck if I can't access the AoT dictionaries from a script. There are way, way too many entries in the dictionaries to store them as individual variables.

Bolt Version:
Unity Version:
Platform(s):
Scripting Backend:
.NET Version (API Compatibility Level):
GOOD, I'M SATISFIED
Satisfaction mark by GhostAegis 2 years ago
Answered

AotDictionary is a different class than Dictionary<TKey, TValue>. You should use:

var dictionary = (AotDictionary)Variables.Application.Get("progress");

Thank you! That makes sense, I did not realize. 

However, this seems to introduce a new problem. For example, when I run this as a test:


public void ReadBoltData(){

var dictionary = (AotDictionary)Variables.Saved.Get("upgrades");
Variables.Application.Set("clonedUpgrades", dictionary);

}

I find that now these both point to the same dictionary, so changes to one make changes to the other. A little research makes it seem like a dictionary is actually a reference to an object, not values, so can I even do what I want in this case, or am I completely off track here? 

You'd have to create a new AotDictionary() and copy the values from the previous one in it, e.g. using a foreach loop. Indeed, dictionaries are reference types in C#.

Okay, that makes a lot more sense. Thank you. I find myself stuck again though, as it seems the item.Key and item.Value usually used to access dictionary key/value pairs during foreach isn't defined for AotDictionary. So a foreach loop doesn't help much because I can't pull the value or key for each entry. As a test example:

        foreach(var item in dictionary){

            Variables.Application.Set(index.ToString(), item.Value);
            index++;

        }

item.Value is showing an error as being undefined for type object. 

Is there are different term I should be using, since AotDictionary is its own class? Does it have a unique type for key/value pairs? Or is there a way I can cast each item into a specific KeyValuePair type in the foreach declaration?


Yes, AotDictionaries are tricky in that way, because they inherit a class that was created before C# generics existed.

Here's how to do it, from memory:

var enumerator = aotDictionary.GetEnumerator();
while (enumerator.MoveNext())
{
   var key = enumerator.Key;
   var value = enumerator.Value;
   // ...
}

In the mid-term, we are attempting to move to fully generic classes in Bolt, even in AOT platforms, thanks for C# generation which is coming to Bolt 2. When that's done, AotDictionary will be deprecated, and new Dictionary units in Bolt would be fully typed (e.g. Dictionary<string, bool[]>, as in your example).

Cool, thank you! That got me going down the road and I was able to get it sorted. 

That'll be slick, I look forward to Bolt 2. Bolt has been nothing short of a miracle for me, and I love using it. You do amazing work!