UIFramework之数据表读取工具
常见数据表配置文件,有使用xml,excel,csv,Jason等等。其实大概思路都一样,都是先读取文件,把数据以某种数据结构的形式存在于代码中。Unity中的数据,我们以Prefab的形式保存下来,需要使用的相关数据时,通过加载Prefab并实例化,来读取Prefab上保存的相关数据即可。下面我们以读取csv文件中的数据为示例:
定义CSV文件读取工具方法:
- /*
- * Name: CSVReader.cs
- * Function: N/A
- *
- * Ver 变更日期 负责人 变更内容
- * ──────────────────────────────────────────────────────────────────────
- * V1.0.0 2016/12/26 http://blog.csdn.net/husheng0
- *
- * Copyright (c). All rights reserved.
- */
- using UnityEngine;
- using System.Collections;
- using System;
- using System.IO;
- using System.Text;
- using System.Collections.Generic;
- /// <summary>
- /// CSV格式文件读取器,把csv文件数据全部读取到List
- ///
- ///
- /// #编号|属性1|属性2
- /// Id|IntValue|StrValue
- /// 1|100|string1
- /// 2|200|string2
- /// </summary>
- public class CSVReader
- {
- //读取文件存在形式
- public List<List<string>> ContentList = new List<List<string>>();
- //读取的文件路径
- public string CSVFileName;
- /// <summary>
- /// 读取CSV文件,保存至ContentList
- /// </summary>
- /// <param name="fileName">文件路径</param>
- public void LoadCSVFile(String fileName)
- {
- CSVFileName = fileName;
- //清空数据
- ContentList.Clear();
- try
- {
- FileStream fs = new FileStream(fileName, FileMode.Open,
- FileAccess.Read, FileShare.ReadWrite);
- StreamReader reader = new StreamReader(fs, Encoding.UTF8);
- string content = reader.ReadToEnd();
- LoadCSVFileContent(content);
- reader.Close();
- fs.Close();
- }
- catch (Exception e)
- {
- Debug.LogException(e);
- }
- }
- /// <summary>
- /// 转化一行数据保存至List
- /// </summary>
- /// <param name="content">一行数据的字符串</param>
- public void LoadCSVFileContent(String content)
- {
- StringReader sr = new StringReader(content);
- string line = null;
- while ((line = sr.ReadLine()) != null)
- {
- line = line.Trim(' ', '\t');
- if (line == "") continue;
- List<string> items = new List<string>();
- items.AddRange(line.Split('|'));
- for (int i = 0; i < items.Count; i++) items[i].Trim(' ', '\t');
- ContentList.Add(items);
- }
- sr.Close();
- }
- /// <summary>
- /// 报错
- /// </summary>
- /// <param name="row">行数</param>
- /// <param name="col">列数</param>
- void LogError(int row, int col)
- {
- if (row - 1 >= ContentList.Count)
- Debug.LogError("Import Data Error At Row " + row + " Col " + col);
- else
- {
- if (col - 1 >= ContentList[row - 1].Count)
- Debug.LogError("Import Data Error At Row " + row + " Col " + col);
- }
- }
- }
定义读取CSV文件的对应Prefab脚本父类:
- using System;
- using UnityEngine;
- using System.Collections.Generic;
- using System.Reflection;
- using Debug = UnityEngine.Debug;
- /// <summary>
- /// 实现自动读取CSV的Prefab脚本基类
- /// </summary>
- public class ImportDatabase : MonoBehaviour
- {
- public List<List<string>> ContentList = new List<List<string>>();
- private string FileName;
- /// <summary>
- /// 导入数据
- /// </summary>
- public void ImportData(CSVReader reader)
- {
- ClearData();
- FileName = reader.CSVFileName;
- Debug.Log("Start Import CSVFile:" + FileName);
- Import2CSVFinished();
- if (reader.ContentList.Count > 2)
- {
- for (int i = 2; i < reader.ContentList.Count; i++)
- {
- ContentList.Add(reader.ContentList[i]);
- }
- }
- else
- {
- Debug.LogError("CSVFile:" + FileName + "Data Empty!");
- return;
- }
- ImportDataInit();
- Import2PrefabFinished();
- Debug.Log("Complete Import CSVFile:" + FileName);
- }
- /// <summary>
- /// 清除数据
- /// </summary>
- public virtual void ClearData()
- {
- ContentList.Clear();
- }
- /// <summary>
- /// 初始化数据到Perfab
- /// </summary>
- public virtual void ImportDataInit()
- {
- }
- /// <summary>
- /// 数据导入Prefab结束后的处理
- /// </summary>
- public virtual void Import2PrefabFinished()
- {
- }
- /// <summary>
- /// 数据导入CSV文件结束后的处理
- /// </summary>
- public virtual void Import2CSVFinished()
- {
- }
- }
- using UnityEngine;
- using System;
- using System.Collections;
- using System.Collections.Generic;
- /// <summary>
- /// 示例
- /// </summary>
- public class ExampleDB : ImportDatabase
- {
- public static ExampleDB Instance = null;
- void Awake()
- {
- if (null == Instance)
- {
- Instance = this; //调用构造函数
- }
- }
- void OnDestroy()
- {
- Instance = null;
- }
- [SerializeField]
- public List<ExampleData> ExampleDataList = new List<ExampleData>();
- public override void ImportDataInit()
- {
- base.ImportDataInit();
- for (int i = 0; i < base.ContentList.Count; i++)
- {
- List<string> tempList = base.ContentList[i];
- ExampleDataList.Add(new ExampleData
- {
- Id = int.Parse(tempList[0]),
- IntValue = int.Parse(tempList[1]),
- StrValue = tempList[2]
- });
- }
- }
- public override void ClearData()
- {
- base.ClearData();
- ExampleDataList.Clear();
- }
- }
- [Serializable]
- public class ExampleData
- {
- public int Id;
- public int IntValue;
- public string StrValue;
- }
导入文件方法,简单点说就是把Prefab加载到Hierarchy目录->导入数据->替换原Prefab文件:
- using System;
- using UnityEngine;
- using UnityEditor;
- using System.Collections.Generic;
- using System.IO;
- using Object = UnityEngine.Object;
- public class CSVFile2PrefabTools
- {
- //预设文件所在的根目录
- public const string PrefabPath =
- "Assets/Resources/Prefabs/Databases/ExampleDB.prefab";
- //CSV文件所在的根目录
- public static string CSVPath =
- Application.dataPath + "/../Datas/ExampleData.csv";
- /// <summary>
- /// 基于配置的prefab自动导入csv功能
- /// </summary>
- [MenuItem("Custom/PrefabTools/CSVFile2Prefab")]
- public static void CSVFile2Prefab()
- {
- ImportDatabase TempDataPrefab = null;
- try
- {
- GameObject prefab = AssetDatabase.LoadAssetAtPath(PrefabPath,
- typeof(GameObject)) as GameObject;
- GameObject TargetDataPrefab = null;
- if (prefab != null)
- {
- TargetDataPrefab = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
- TempDataPrefab = TargetDataPrefab.GetComponent<ImportDatabase>();
- if (TempDataPrefab != null)
- {
- CSVReader tempCSV = new CSVReader();
- tempCSV.LoadCSVFile(CSVPath);
- TempDataPrefab.ImportData(tempCSV);
- PrefabUtility.ReplacePrefab(TargetDataPrefab, prefab);
- GameObject.DestroyImmediate(TargetDataPrefab);
- }
- }
- else
- {
- Debug.LogError(PrefabPath + " Is Load Failure!");
- }
- }
- catch (Exception exp)
- {
- Debug.LogError(exp.Message);
- Debug.LogError(exp.StackTrace);
- if (exp.InnerException != null)
- {
- Debug.LogError(exp.InnerException.Message);
- Debug.LogError(exp.InnerException.StackTrace);
- }
- }
- //保存场景
- EditorApplication.SaveScene();
- }
- }
- using UnityEngine;
- using System.Collections;
- #if UNITY_EDITOR
- using UnityEditor;
- #endif
- /// <summary>
- /// 为Prefab预设添加单个导入操作
- /// </summary>
- public abstract class BaseDBEditor : Editor
- {
- private ImportDatabase DataBase;
- void OnEnable()
- {
- DataBase = target as ImportDatabase;
- }
- public override void OnInspectorGUI()
- {
- GUILayout.BeginHorizontal();
- if (GUILayout.Button("ImportData", GUILayout.Width(80f)))
- {
- string dataPath = EditorUtility.OpenFilePanel("Select a CSVFile", "", "csv");
- if (!dataPath.Contains(".csv")) return;
- ImportData(dataPath);
- Debug.Log("CSVFilePath" + dataPath);
- }
- GUILayout.EndHorizontal();
- DrawDefaultInspector();
- }
- private void ImportData(string fileName)
- {
- CSVReader tempCSV = new CSVReader();
- tempCSV.LoadCSVFile(fileName);
- DataBase.ImportData(tempCSV);
- }
- }
- /// <summary>
- /// ExampleDB
- /// </summary>
- [CustomEditor(typeof(ExampleDB))]
- public class ExampleDBEditor : BaseDBEditor
- {
- }
- using UnityEngine;
- using System.Collections;
- /// <summary>
- /// 测试文件
- /// </summary>
- public class Test : MonoBehaviour
- {
- UnityEngine.Object obj = null;
- GameObject go = null;
- void Awake()
- {
- obj = Resources.Load("Prefabs/Databases/ExampleDB");
- if (null == obj)
- {
- return;
- }
- else
- {
- Debug.LogError("--->Load success");
- go = GameObject.Instantiate(obj) as GameObject;
- go.SetActive(true);
- if (null == ExampleDB.Instance) return;
- foreach (ExampleData temp in ExampleDB.Instance.ExampleDataList)
- {
- Debug.LogError(temp.Id + "-->" + temp.IntValue + "-->" + temp.StrValue);
- }
- }
- }
- void OnDisable()
- {
- if (null != go) Object.Destroy(go);
- }
- }
测试结果:
====================================================================
结束。