在Unity3d中编写和读取一些转换为文本文件的简便方法?

时间:2016-09-06 09:46:31

标签: json serialization unity3d io transform

这完全在Unity3D中,我有一个100 Transform

的数组

我想将这些内容写入PC桌面上的文件,然后再阅读它们。

考虑......

 // 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;

..然后类似地阅读它,只需手动解析文本格式。有点像...

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();
  }

但这似乎很幼稚。什么是&#34;简单的Unity方式&#34;这样做?

2 个答案:

答案 0 :(得分:1)

您可以使用Binary Serialization

创建以下结构:

[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);
    }
}

保存方法:

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);
    }
}

加载方法:

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:据我所知,你无法Transform创建GameObject,因此请将SerializebleTransform的数据读入Transform有点手动

答案 1 :(得分:1)

您可以使用JsonPlayerprefs来保存转换。这是一个TransformSaver扩展类,可以做到这一点:

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

json脚本,反之亦然:

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;
    }
}

<强>用法

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);
    }
}

它并不完美,可以改进。改进包括使LoadTransform函数将transform数组作为参数而不是返回数组。