This is strictly in Unity3D, I have an array of 100 Transform
,
I want to write those to a file on the PC desktop, and later read them.
Consider ...<
You can use Json
and the Playerprefs
to save the Transform. This is a TransformSaver
extension class that can do that:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public static class TransformSaver
{
[System.Serializable]
public class TransformInfo
{
public Vector3 pos;
public Quaternion rot;
public Vector3 scale;
}
//Save Transform
public static void SaveTransform(this Transform trans, Transform[] tranformToSave)
{
TransformInfo[] trnfrm = new TransformInfo[tranformToSave.Length];
for (int i = 0; i < trnfrm.Length; i++)
{
trnfrm[i] = new TransformInfo();
trnfrm[i].pos = tranformToSave[i].position;
trnfrm[i].rot = tranformToSave[i].rotation;
trnfrm[i].scale = tranformToSave[i].localScale;
}
string jsonTransform = JsonHelper.ToJson(trnfrm, true);
PlayerPrefs.SetString("transform", jsonTransform);
}
//Load Transform
public static Transform[] LoadTransform(this Transform trans)
{
string jsonTransform = PlayerPrefs.GetString("transform");
if (jsonTransform == null)
{
return null;
}
//Debug.Log("Loaded: " + jsonTransform);
TransformInfo[] savedTransforms = JsonHelper.FromJson<TransformInfo>(jsonTransform);
GameObject[] gameObjects = new GameObject[savedTransforms.Length];
Transform[] loadedTransforms = new Transform[savedTransforms.Length];
for (int i = 0; i < gameObjects.Length; i++)
{
gameObjects[i] = new GameObject("_");
gameObjects[i].hideFlags = HideFlags.HideAndDontSave;
loadedTransforms[i] = gameObjects[i].transform;
loadedTransforms[i].position = savedTransforms[i].pos;
loadedTransforms[i].rotation = savedTransforms[i].rot;
loadedTransforms[i].localScale = savedTransforms[i].scale;
}
return loadedTransforms;
}
public static void CopyTransform(this Transform trans, Transform source, Transform target, bool createNewInstance = false)
{
if (source == null)
{
return;
}
if (target == null || createNewInstance)
{
GameObject obj = new GameObject("_");
obj.hideFlags = HideFlags.HideAndDontSave;
target = obj.transform;
}
target.position = source.position;
target.rotation = source.rotation;
target.localScale = source.localScale;
}
public static void CopyTransform(this Transform trans, Transform[] source, Transform[] target, bool createNewInstance = false)
{
if (source == null || source.Length <= 0)
{
return;
}
for (int i = 0; i < target.Length; i++)
{
CopyTransform(null, source[i], target[i], createNewInstance);
if (i >= target.Length - 1)
{
break;
}
}
}
}
JsonHelper
script for converting arrays to json
and vice versa:
using UnityEngine;
using System.Collections;
using System;
public class JsonHelper
{
public static T[] FromJson<T>(string json)
{
Wrapper<T> wrapper = UnityEngine.JsonUtility.FromJson<Wrapper<T>>(json);
return wrapper.Items;
}
public static string ToJson<T>(T[] array, bool prettyPrint)
{
Wrapper<T> wrapper = new Wrapper<T>();
wrapper.Items = array;
return UnityEngine.JsonUtility.ToJson(wrapper, prettyPrint);
}
[Serializable]
private class Wrapper<T>
{
public T[] Items;
}
}
Usage:
using UnityEngine;
using System.Collections;
public class TransformTest : MonoBehaviour
{
public Transform[] objectToSave;
// Use this for initialization
void Start()
{
//Save Transform
transform.SaveTransform(objectToSave);
//Load Transform
Transform[] loadedTransform = transform.LoadTransform();
transform.CopyTransform(loadedTransform, objectToSave);
}
}
It's not perfect and can be improved. Improvement includes making the LoadTransform
function take transform
array as parameter instead of returning an array.
You can use Binary Serialization.
Create following structs:
[Serializable]
public struct SerializebleVector
{
public float x, y, z, w;
public SerializebleVector(float x, float y, float z, float w = 0f)
{
this.x = x;
this.y = y;
this.z = z;
this.w = w;
}
public static explicit operator SerializebleVector(Quaternion a)
{
return new SerializebleVector(a.x, a.y, a.z, a.w);
}
public static implicit operator SerializebleVector(Vector3 a)
{
return new SerializebleVector(a.x, a.y, a.z);
}
}
[Serializable]
public struct SerializebleTransform
{
SerializebleVector position;
SerializebleVector rotation;
SerializebleVector scale;
public SerializebleTransform(Transform tr)
{
position = tr.position;
rotation = (SerializebleVector) tr.rotation;
scale = tr.lossyScale;
}
public static implicit operator SerializebleTransform(Transform tr)
{
return new SerializebleTransform(tr);
}
}
Save method:
public static void Save(Transform[] ts )
{
var data = new List<SerializebleTransform>();
foreach (var t in ts)
{
data.Add(t);
}
BinaryFormatter bf = new BinaryFormatter();
using (FileStream file = File.Create (Application.persistentDataPath + "/savedTransforms.dat"))
{
bf.Serialize(file, data);
}
}
Load Method:
public static void Load(out List<SerializebleTransform> ts)
{
if(File.Exists(Application.persistentDataPath + "/savedTransforms.dat"))
{
BinaryFormatter bf = new BinaryFormatter();
using (FileStream file = File.Open(Application.persistentDataPath + "/savedTransforms.dat", FileMode.Open))
{
var data = (List<SerializebleTransform>)bf.Deserialize(file);
return data;
}
}
else
ts = null;
}
PS: As far as I know you can't create Transform
without GameObject
, so read data from SerializebleTransform
into Transform
kind of manually.