Export Const Class with JSON

Hello,

I’m using a class to define a bunch of constants within my game. Like this:

public class GameConstants{

   public const int BUILD_TIME = 20;
   public const int BUILD_COST = 100;
   public const int BUILD_TYPE = 2;
}
//etc...

I wish to be able to export this class to a JSON file so I can share among other 3rd parties. However, it’s as if the Json doesn’t even see, or read the ‘const’ variables. It returns an empty JSON.

However, if I include a normal variable within that class ‘public int _hello = 0’. Then the JSON will pick that up, and include it into the JSON string, but not the CONSTS.

static void ExportConstJson(){

		GameConstants _object = new GameConstants();
		string _json = JsonUtility.ToJson(_object);
		print("Json: " + _json);
	}

Is there any reason for this? Or a solution?

Thanks.

Const fields are not variables, they are constants. They are pretty much the exact opposite of variables. Constants are never serialized by any serialization system since they can never be deserialized as they are readonly and static. Static fields are never serialized either.

You basically have two options:

  • Store those “constants” in actual variables and serialize them in Unity. You usually would use a ScriptableObject for this.
  • Reverse the logic and store those setting in a JSON file and load that JSON file at runtime into variables. Actually a lot companies use this approach as they can hand over the json file to the gamedesigner (who often is not a programmer) and let him do the balancing. In the final build you usually integrate the JSON into the game so it can’t be changed that easy from outside.

edit
Here’s a small helper class that lets you easily export all public static fields (which includes const fields) of a given class type as JSON:

using System.Text;
using System.Reflection;
using System;

public static class StaticExporter
{
    public static string Export<T>()
    {
        return Export(typeof(T));
    }
    public static string Export(Type aType)
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendLine("{");

        var fields = aType.GetFields(BindingFlags.Static | BindingFlags.Public);
        for(int i = 0; i < fields.Length; i++)
        {
            var t = fields*.FieldType;*

var v = fields*.GetValue(null);*
SerializeFieldName(3, fields*.Name, sb);*
if (IsNumber(t))
sb.Append(Convert.ToDouble(v));
else if (t == typeof(bool))
sb.Append((bool)v ? “true” : “false”);
else if (t == typeof(string))
sb.Append(‘"’).Append((string)v).Append(“"”);
else
sb.Append(“null”);
if (i < fields.Length)
sb.Append(“,”);
sb.AppendLine();
}
sb.AppendLine(“}”);
return sb.ToString();
}
private static void SerializeFieldName(int aPrefix, string aName, StringBuilder aSb)
{
aSb.Append(’ ', aPrefix);
aSb.Append(‘"’).Append(aName).Append("" = ");
}

private static bool IsNumber(System.Type aType)
{
if (!aType.IsValueType)
return false;
return (
aType == typeof(int) || aType == typeof(uint) ||
aType == typeof(long) || aType == typeof(ulong) ||
aType == typeof(short) || aType == typeof(ushort) ||
aType == typeof(byte) || aType == typeof(sbyte) ||
aType == typeof(float) || aType == typeof(double)
);
}
}
So in your case you just have to do:
Debug.Log(StaticExporter.Export());
Note that this method only supports usual number types (see IsNumber), boolean and strings. All other static fields will be exported as “null”. Though feel free to extend it if you need to.