Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by CrashCZ · Feb 15, 2018 at 10:29 AM · jsonsavingdatasave datautility

JsonUtility.ToJson returns empty file

Hello I hae this script that should sae data about GameObjects to a json file:

     public void SaveData()
     {
         List<string> jsonStrings = new List<string>();
         foreach (GameObject sceneObject in toolbar.sceneObjects)
         {
             string name = sceneObject.name;
             jsonStrings.Add(name);
             string tag = sceneObject.tag;
             jsonStrings.Add(tag);
             Vector3 position = sceneObject.transform.position;
             jsonStrings.Add(position.ToString());
             Vector3 rotation = sceneObject.transform.eulerAngles;
             jsonStrings.Add(rotation.ToString());
             Vector3 scale = sceneObject.transform.localScale;
             jsonStrings.Add(scale.ToString());
             Component meshFilter = sceneObject.GetComponent<MeshFilter>();
             jsonStrings.Add(meshFilter.ToString());
             Component Renderer = sceneObject.GetComponent<Renderer>();
             jsonStrings.Add(Renderer.ToString());
             Component collider = sceneObject.GetComponent<Collider>();
             jsonStrings.Add(collider.ToString());
             Component rigidbody = sceneObject.GetComponent<Rigidbody>();
             jsonStrings.Add(rigidbody.ToString());
             Component light = sceneObject.GetComponent<Light>();
             foreach(MonoBehaviour script in sceneObject.GetComponents<MonoBehaviour>())
             {
                 string scriptName = script.name;
                 jsonStrings.Add(scriptName);
                 if(script.name == "ChildObject")
                 {
                     GameObject extender = sceneObject.GetComponent<ChildObject>().childObject;
                     jsonStrings.Add(extender.ToString());
                 }
                 if(script.name == "Portal")
                 {
                     Vector3 coordinates = sceneObject.GetComponent<Portal>().coordinates;
                     jsonStrings.Add(coordinates.ToString());
                     GameObject player = sceneObject.GetComponent<Portal>().player;
                     jsonStrings.Add(player.ToString());
                 }
                 if(script.name == "YPad")
                 {
                     bool touching = sceneObject.GetComponent<YPad>().touching;
                     jsonStrings.Add(touching.ToString());
                     AudioClip sound = sceneObject.GetComponent<YPad>().launch;
                     jsonStrings.Add(sound.ToString());
                 }
                 if(script.name == "SetPlayerPrefs")
                 {
                     int thislevel = sceneObject.GetComponent<SetPlayerPrefs>().ThisLevel;
                     jsonStrings.Add(thislevel.ToString());
                     int thislevelmaxscore = sceneObject.GetComponent<SetPlayerPrefs>().ThisLevelMaxScore;
                     jsonStrings.Add(thislevelmaxscore.ToString());
                     GameObject player = sceneObject.GetComponent<SetPlayerPrefs>().Player;
                     jsonStrings.Add(player.ToString());
                 }
             }
         }
         string jsonData = JsonUtility.ToJson(jsonStrings, true);
         File.WriteAllText(localLevelLocation + "/" + properties.levelName + "_data.json" , jsonData);
     }

But the file that is created is empty except of two curly brackets

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by upasnavig90 · Feb 15, 2018 at 11:13 AM

HI, please try using a model class, where you take all the fields required and use the object of that class for parsing in json.

you can look at this for reference:

 [System.Serializable]
 public class ToolBar {
 
     public string hello;
     public string hi;
 }
 
 
 
     ToolBar toolBar;
     void Awake()
     {
         SaveData ();
     }
     public void SaveData()
     {
         toolBar = new ToolBar ();
         toolBar.hello="Hello";
         toolBar.hi = "hi";
                string jsonData = JsonUtility.ToJson(toolBar, true);
         File.WriteAllText(Application.dataPath+"/" + "_data.json" , 
                 jsonData);
     }
 }



Note: if you want to save the whole scene, its better to use assetBundle or scriptable objects.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image CrashCZ · Feb 15, 2018 at 12:11 PM 0
Share

Thank you. I'll try this

avatar image
1

Answer by Bunny83 · Feb 15, 2018 at 12:26 PM

You have two main problems here. First Unity's JsonUtility only supports an object as root element. However you pass a string array. Second the way you try to "pack" your data makes not much sense. You just convert every thing to strings and create one big linear array of strings.


Also serializing something like jsonStrings.Add(Renderer.ToString()); would just save the class name of the renderer, nothing else. The same is true for your collider, meshfilter, rigidbody and light. You also iterate through all monobehaviour components adding more unstructured data in arbitrary order. In short the data inside your string array is pretty useless since it doesn't really contain the necessary data nor does it contain it in a way it can be read again in a meaningful way.


You would need to do two main changes. First of all you have to actually save meaningful information that is required to restore the current state. Store the information in a structured way.


Keep in mind that JSON has no built-in way to serialize cross references between objects. For example for your "Portal" script you seem to try to save a reference to another gameobject (the player). As i already said currently you just store the name of the gameobject which however can be ambiguous. If the object you want to reference is actually saved as well you can simply serialize the InstanceId of each object and just use that Id to reference other objects within the same save file. Note that the instanceId can not be used to reference objects between different sessions. So the data need to be self-contained. When you recreate or load the same data again each object will have different instance ids.


Unity's JsonUtility isn't really suited for serializing complete gameobjects structures. It's also quite limited as it can only object map your data. So you would need to pack all your data into custom objects that can be serialized by Unity (as upasnavig90 said). To actually save a whole scene the JsonUtility is not a good choice. If you like to save and restore your data in a manual approach you may want to use a more flexible JSON framework like my SimpleJSON ^^.


With the files "SimpleJSON.cs" and "SimpleJSONUnity.cs" you can do something like:

 public void SaveData()
 {
     JSONObject root = new JSONObject();
     JSONArray objs = root["sceneObjects"].AsArray();
     foreach (GameObject sceneObject in toolbar.sceneObjects)
     {
         JSONObject obj = objs[-1].AsObject();
         obj["name"] = sceneObject.name;
         obj["tag"] = sceneObject.tag;
         obj["id"] = sceneObject.GetInstanceID();
         JSONArray components = obj["components"].AsArray();
         foreach(Component comp in sceneObject.GetComponents<Component>())
         {
             JSONObject jcomp = components[-1].AsObject();
             string type = comp.GetType().Name;
             jcomp["type"] = type;
             jcomp["id"] = comp.GetInstanceID();
             if (type == "Transform")
             {
                 Transform t = (Transform)comp;
                 jcomp["position"] = t.position;
                 jcomp["rotation"] = t.eulerAngles;
                 jcomp["scale"] = t.localScale;
                 if (t.parent != null)
                     jcomp["parent"] = t.parent.GetInstanceID();
             }
             else if (type == "BoxCollider")
             {
                 BoxCollider c = (BoxCollider)comp;
                 jcomp["center"] = c.center;
                 jcomp["size"] = c.size;
                 jcomp["isTrigger"] = c.isTrigger;
             }
             else if (type == "SphereCollider")
             {
                 SphereCollider c = (SphereCollider)comp;
                 jcomp["center"] = c.center;
                 jcomp["radius"] = c.radius;
             }
             
             // [ ... ]
             
         }
     }
     File.WriteAllText(localLevelLocation + "/" + properties.levelName + "_data.json" , root.ToString(3));
 }

Note this is just an example. Also there are several edge cases. Creating a whole scene from scratch would mean you have to serialize everything (literally EVERYTHING). So a MeshFilter will reference a Mesh object, so you have to serialize the Mesh as well. A MeshRenderer references a material, so the material need to be serialized. A material might reference a texture so you need to serialize the texture. At some point you may want / need to reference actual assets in your game instead of storing it along in the save game file. However this complicates things a bit since you need a way to uniquely identify those assets. Things which you usually want to reference would be materials, meshes, textures, audioclips, ...


That's why saving a whole scene isn't an easy task and hasn't been solved in a single "once-and-for-all" solution. Most savegames would be customized for the exact purpose. For example instead of recreating the whole gameobjects from scratch most dynamic scenes rely on prefabs. Though that means you have to remember which prefab was used to create a certain object. Also, same problem as above, you have to have a way to uniquely identify each prefab.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

78 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Transfer data to/from server in mobile 0 Answers

[Serialize] Attribute with JSON 1 Answer

Don't Destroy on Load Object and GameData 1 Answer

Problem when saving and loading 1 Answer

Why are JSON Libraries even necessary? Isn't it Native? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges