Easy way to write and read some Transform to a text file in Unity3d?

人盡茶涼 提交于 2020-01-11 11:19:12

问题


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 ...

 // write to desktop...
 string s = "";
 for ( int i=0; i< sendMe.Length; ++i )
    {
    Transform tt = sendMe[i].transform;
    s = s +tt.position.x +"," +tt.position.x +"," ...etc... "\n";
    }

 string d = System.Environment.GetFolderPath(
     System.Environment.SpecialFolder.DesktopDirectory);
 string path = System.IO.Path.Combine(d, "happyData.txt" );

 System.IO.File.Delete(path);
 System.IO.File.WriteAllText(path,s);
 return;

.. and then read it similarly, just manually parsing the text format. Something like...

public ReadTrackFromDesktopFile()
  {
  GetSplineGetReady("development");
  string tt = File.ReadAllText( .. path as above);
  List<string> ts = new List<string>(
    tt.Split(new string[] { "\r","\n" },
    StringSplitOptions.RemoveEmptyEntries) );
  foreach (string t in ts)
    {
    string[] parts = t.Split(',');
    Vector3 pos = new Vector3(parts[0],parts[1],parts[2]);
    Quaternion rot = new Quaternion(parts[3],parts[4],parts[5],parts[6]);
    GetSplineOneNode(pos, rot);
    }
  GetSplineFinalise();
  }

But this seems naive. What's the "simple Unity way" to do this?


回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/39345820/easy-way-to-write-and-read-some-transform-to-a-text-file-in-unity3d

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!