- Home /
Storing tag strings in an array, from an already existing array of gameobjects with different tags.
I don't often ask any questions here. I tend to read documents and troubleshoot my own problems and figure them out, but this one is stumping me hard.
I have a 3D stageBuilder/mapMaker scene set up and it works by having an array of empty objects(We'll call them EMs for short), all parented under one gameobject. There's no instantiation in progress, but manipulation towards the empty gameobjects by giving them sharedMesh's, collision, layers, and tags.
My problem is that I want to save all of my EMs and their attributes on a JSON.txt file, so that if someone were to make a custom stage/map, I'd be able to read it into the game and load it.
Is it possible to get a string array pulled from an array of gameobjects with different tags? All of the EMs won't be used, so some of them will be called "empty", while some are used and called "ground". I want to try and get their respective elements read, and then with their elements lined up, also fill in an empty string array I made. I hope I wasn't too confusing. I'm not even sure JSON allows this kind if mock-up.
My other solutions, that worked, was to create EVERY int/string myself calling them "tag0","tag1"..."tag100". But I'd also have to do this for their position x, y and z, and their layers and so on. I want to cheat it essentially.
My code's a little messy but this is my save/load system.
public GameObject[] EmptyObj;
public GameObject MeshCalc;
public string[] tagData;
public int index;
public int rawIndex;
int layerData0;
int layerData1;
int meshData0;
int meshData1;
Vector3 positionData;
Quaternion rotationData;
void Start()
{
index = EmptyObj.Length;
rawIndex = tagData.Length;
}
public void Save()
{
JSONObject Empty = new JSONObject();
//Save Tags
tagData[rawIndex] = EmptyObj[index].GetComponent<EmptyObjectMeshCalc>().tagName;
Empty.Add("tag" + EmptyObj[index], tagData[index]);
//Save Layer
layerData0 = EmptyObj[0].layer;
layerData1 = EmptyObj[1].layer;
Empty.Add("layer0", layerData0);
Empty.Add("layer1", layerData1);
//Save Mesh
meshData0 = EmptyObj[0].GetComponent<EmptyObjectMeshCalc>().i;
meshData1 = EmptyObj[1].GetComponent<EmptyObjectMeshCalc>().i;
Empty.Add("meshData0", meshData0);
Empty.Add("meshData1", meshData1);
//Save Position
JSONArray position0 = new JSONArray();
position0.Add(EmptyObj[0].transform.position.x);
position0.Add(EmptyObj[0].transform.position.y);
position0.Add(EmptyObj[0].transform.position.z);
Empty.Add("position0", position0);
JSONArray position1 = new JSONArray();
position1.Add(EmptyObj[1].transform.position.x);
position1.Add(EmptyObj[1].transform.position.y);
position1.Add(EmptyObj[1].transform.position.z);
Empty.Add("position1", position1);
//Save Rotation
JSONArray rotation0 = new JSONArray();
rotation0.Add(EmptyObj[0].transform.eulerAngles.x);
rotation0.Add(EmptyObj[0].transform.eulerAngles.y);
rotation0.Add(EmptyObj[0].transform.eulerAngles.z);
Empty.Add("rotation0", rotation0);
JSONArray rotation1 = new JSONArray();
rotation1.Add(EmptyObj[1].transform.eulerAngles.x);
rotation1.Add(EmptyObj[1].transform.eulerAngles.y);
rotation1.Add(EmptyObj[1].transform.eulerAngles.z);
Empty.Add("rotation1", rotation1);
Debug.Log(Empty.ToString());
string path = Application.persistentDataPath + "/MapData.json";
File.WriteAllText(path, Empty.ToString());
}
public void Load()
{
string path = Application.persistentDataPath + "/MapData.json";
string jsonFile = File.ReadAllText(path);
JSONObject emptyJson = (JSONObject)JSON.Parse(jsonFile);
//SET TAGS
tagData[index] = emptyJson["tag"];
//SET LAYERS
layerData0 = emptyJson["layer0"];
layerData1 = emptyJson["layer1"];
EmptyObj[0].layer = layerData0;
EmptyObj[1].layer = layerData1;
//SET MESH
meshData0 = emptyJson["meshData0"];
meshData1 = emptyJson["meshData1"];
EmptyObj[0].GetComponent<EmptyObjectMeshCalc>().i = meshData0;
EmptyObj[1].GetComponent<EmptyObjectMeshCalc>().i = meshData1;
EmptyObj[0].GetComponent<MeshFilter>().sharedMesh = MeshCalc.GetComponent<CreateObjects>().Platforms[meshData0].GetComponent<MeshFilter>().sharedMesh;
EmptyObj[0].AddComponent<MeshCollider>().sharedMesh = MeshCalc.GetComponent<CreateObjects>().Platforms[meshData0].GetComponent<MeshFilter>().sharedMesh;
EmptyObj[1].GetComponent<MeshFilter>().sharedMesh = MeshCalc.GetComponent<CreateObjects>().Platforms[meshData1].GetComponent<MeshFilter>().sharedMesh;
EmptyObj[1].AddComponent<MeshCollider>().sharedMesh = MeshCalc.GetComponent<CreateObjects>().Platforms[meshData1].GetComponent<MeshFilter>().sharedMesh;
//SET POSITION
EmptyObj[0].transform.position = new Vector3(emptyJson["position0"].AsArray[0], emptyJson["position0"].AsArray[1], emptyJson["position0"].AsArray[2]);
EmptyObj[1].transform.position = new Vector3(emptyJson["position1"].AsArray[0], emptyJson["position1"].AsArray[1], emptyJson["position1"].AsArray[2]);
//SET ROTATION
EmptyObj[0].transform.eulerAngles = new Vector3(emptyJson["rotation0"].AsArray[0], emptyJson["rotation0"].AsArray[1], emptyJson["rotation0"].AsArray[2]);
EmptyObj[1].transform.eulerAngles = new Vector3(emptyJson["rotation1"].AsArray[0], emptyJson["rotation1"].AsArray[1], emptyJson["rotation1"].AsArray[2]);
Debug.Log("Loaded");
}
And every EM has this script attached:
public class EmptyObjectMeshCalc : MonoBehaviour
{
public int i;
public string tagName;
}
If you need anything else, I'd be happy to provide. Thanks again in advance!
Answer by mchts · Mar 11, 2019 at 09:20 AM
Create an entity for your pattern. In your case that would be like :
using System;
[Serializable]
public class EmptyObjData {
public string tag;
public List<float> position;
public List<float> rotation; //as euler angles
public float layer;
}
Then on Save method get all your gameobjects in an array and do this loop
public void Save() {
GameObject[] arr = [your empty gameobjects];
var wrapper = new EmptyObjDataWrapper();
var dataList = new List<EmptyObjData>();
for (int i = 0; i < arr.Length; i++) {
var t = arr[i].transform;
var d = new EmptyObjData {
tag = arr[i].GetComponent<EmptyObjectMeshCalc>().tagName,
position = new List<float>() { t.position.x, t.position.y, t.position.z },
rotation = new List<float>() { t.rotation.eulerAngles.x, t.rotation.eulerAngles.y, t.rotation.eulerAngles.z },
layer = arr[i].layer
};
dataList.Add(d);
}
wrapper.emptyObjDataArray = dataList.ToArray();
string jsonFile = JsonUtility.ToJson(wrapper);
//Then save json as text with the same (MapData.json in your case)
}
When you deserialize this saved data you will get wrapper class. So set all values back again in a for loop
public void Load() {
string path = Application.persistentDataPath + "/MapData.json";
string jsonFile = File.ReadAllText(path);
//JSONObject emptyJson = (JSONObject)JSON.Parse(jsonFile);
EmptyObjDataWrapper wrapper = JsonUtility.FromJson<EmptyObjDataWrapper >(jsonFile);
//JsonUtility.FromJson<List<EmptyObjData>>(emptyJson);
GameObject[] arr = [your empty gameobjects];
for (int i = 0; i < wrapper.emptyObjDataArray.Count; i++) {
arr[i].tag = wrapper.emptyObjDataArray[i].tag;
arr[i].transform.position = new Vector3(wrapper.emptyObjDataArray[i].position[0], wrapper.emptyObjDataArray[i].position[1], wrapper.emptyObjDataArray[i].position[2]);
wrapper.emptyObjDataArray[i].transform.rotation = Quaternion.Euler(new Vector3(wrapper.emptyObjDataArray[i].rotation[0], wrapper.emptyObjDataArray[i].rotation[1], wrapper.emptyObjDataArray[i].rotation[2]));
arr[i].layer = wrapper.emptyObjDataArray[i].layer
}
}
using System;
[Serializable]
public class EmptyObjDataWrapper {
public EmptyObjData[] emptyObjDataArray;
}
Thanks very much! I've played around with the code and matched it to what I needed, although, I'm getting "cannot cast from source type" error on my loading void. $$anonymous$$y new code's here:
public GameObject[] empty;
[Serializable]
public class EmptyObjData
{
public string tag;
public List<float> pos;
public List<float> rot;
public List<float> scl;
public int lyr;
}
public void Save()
{
string path = Application.persistentDataPath + "/$$anonymous$$apData.json";
GameObject[] arr = empty;
var dataList = new List<EmptyObjData>();
for (int i = 0; i < arr.Length; i++)
{
var t = arr[i].transform;
var d = new EmptyObjData
{
tag = arr[i].transform.tag,
pos = new List<float>() { t.position.x, t.position.y, t.position.z },
rot = new List<float>() { t.rotation.eulerAngles.x, t.rotation.eulerAngles.y, t.rotation.eulerAngles.z },
lyr = arr[i].layer
};
dataList.Add(d);
}
Debug.Log(dataList.ToString());
JsonUtility.ToJson(dataList);
File.WriteAllText(path, dataList.ToString());
}
public void Load$$anonymous$$ap()
{
string path = Application.persistentDataPath + "/$$anonymous$$apData.json";
string jsonFile = File.ReadAllText(path);
JSONObject emptyJson = (JSONObject)JSON.Parse(jsonFile); //Where the apparent error is located
List<EmptyObjData> list = JsonUtility.FromJson<List<EmptyObjData>>(emptyJson);
GameObject[] arr = empty;
Debug.Log(path.ToString());
for (int i =0; i < list.Count; i++)
{
arr[i].tag = list[i].tag;
arr[i].transform.position = new Vector3(list[i].pos[0], list[i].pos[1], list[i].pos[2]);
arr[i].transform.rotation = Quaternion.Euler(list[i].rot[0], list[i].rot[1], list[i].pos[2]);
arr[i].transform.localScale = new Vector3(list[i].scl[0], list[i].scl[1], list[i].scl[2]);
arr[i].layer = list[i].lyr;
}
}
I'm certain that I can read more about this error and figure it out. Or maybe I edited the code wrong. If I did however, please let me know where if you could. Otherwise, thank you very much for helping me get on track! You're awesome!
Your answer
Follow this Question
Related Questions
SerializationException: Type UnityEngine.Vector3 is not marked as Serializable. 1 Answer
check if my variable is in the same position as the array 2 Answers
List of bools assigned to each Gameobject in List/Array 0 Answers
Get object child list with tag 2 Answers
Implicit Downcast on array object and clearing array 0 Answers