0

I have the following collection in C# which is sent to Google servers (Firebase Remote Config).

I want to add values in the Unity inspector itself and not in code. As you can see, the values can be any type (bool, string, int, etc).

System.Collections.Generic.Dictionary<string, object> defaults =
            new System.Collections.Generic.Dictionary<string, object>();

        defaults.Add("config_test_string", "default local string");
        defaults.Add("config_test_int", 1);
        defaults.Add("config_test_float", 1.0);
        defaults.Add("config_test_bool", false);

Basically I've done this:

[Serializable]
    public struct RemoteValueConfig {
        public string key;
        public object defaultValue;
    }



    public RemoteValueConfig[] valuesToFetch;

But it doesn't work, since the "object" type won't show up in the Unity inspector. If I only needed string objects, I would simply replace defaultValue which is of type object, with a string type and this would solve my problem. But I can have int's, float's, strings, bool, etc.

How can I populate values in this scenario (and what to use), to work with Unity inspector?

Lews Therin
  • 3,707
  • 2
  • 27
  • 53
rootpanthera
  • 2,731
  • 10
  • 33
  • 65

2 Answers2

1

Unity's inspector doesn't support generics, so the answer is a little more complex than what you'd normally do in C#. But, according to Unity's answer community, you can provide concrete implementations of a shared base class to get around this limitation:

EDIT: Changed these from structs to classes and added the default constructors in the subclasses to make it compilable

[Serializable]
public class RemoteValueConfigBase<T>
{
    public string Key;
    public T DefaultValue;

    public RemoteValueConfigBase(string key, T defaultValue)
    {
        Key = key;
        DefaultValue = defaultValue;
    }
}

[Serializable]
public class RemoteValueConfigStr : RemoteValueConfigBase<string>
{
    public RemoteValueConfigStr(string key, string defaultValue) : base(key, defaultValue)
    { }
}

[Serializable]
public class RemoteValueConfigBool : RemoteValueConfigBase<bool>
{
    public RemoteValueConfigBool(string key, bool defaultValue) : base(key, defaultValue)
    { }
}

[Serializable]
public class RemoteValueConfigInt : RemoteValueConfigBase<int>
{
    public RemoteValueConfigInt(string key, int defaultValue) : base(key, defaultValue)
    { }
}

[Serializable]
public class RemoteValueConfigDouble : RemoteValueConfigBase<double>
{
    public RemoteValueConfigDouble(string key, double defaultValue) : base(key, defaultValue)
    { }
}

...etc

Then your collection of defaults would be able to be this:

EDIT: Note I changed it from a dictionary to a list because your object that you provided was already a key/value format - but this answer is meant to point you in the right direction as I'm unsure exactly how you intend to use it. The base classing still is the same.

var defaults = new List<RemoteValueConfigBase<object>();
defaults.Add(new RemoteValueConfigStr("config_test_string", "default local string"));
defaults.Add(new RemoteValueConfigInt("config_test_int", 1));
defaults.Add(new RemoteValueConfigDouble("config_test_float", 1.0));
defaults.Add(new RemoteValueConfigBool("config_test_bool", false));

For more details check out this link

Robert Petz
  • 2,718
  • 4
  • 23
  • 52
0

I think you're going to need to make a "wrapper object" that does get displayed in the inspector (you will also need a custom inspector script for it).

For example, in a idle-clicker game I'm working on, I have this set up to handle the different value types an upgrade can have (float or integer):

public abstract class UpgradeValueWrapper { }

public class UpgradeIntValue : UpgradeValueWrapper {
    public int value;
    public UpgradeIntValue(int v) {
        value = v;
    }
}

public class UpgradeFloatValue : UpgradeValueWrapper {
    public float value;
    public UpgradeFloatValue(float v) {
        value = v;
    }
}

Your dictionary would then be <string,AbstractWrapper> with a custom inspector script that handles the translation for display. By declaring the type as being something more specific than object (which could literally be anything) that has a known number of subtypes that wrap around the values you want, it becomes a lot easier to insure that the data is something that can be handled.

I don't know if it would actually work, I've only built one or two inspector scripts and I always came away from it thinking "ugh, I don't ever want to do that again." A custom inspector script by itself might also be enough, but I don't know if trying to write one for object would work; I suspect not.