Unity从StreamingAssets加载CSV失败:ID列找不到问题求助
解决Unity从StreamingAssets加载CSV时找不到"ID"列的问题
问题根源
从StreamingAssets通过UnityWebRequest加载CSV时,导致表头解析错误的常见原因:
- 换行符跨平台不一致,原正则无法正确分割行
- CSV文件带UTF-8 BOM头,导致表头字段被额外字符污染
- 未正确使用协程等待UnityWebRequest下载完成,拿到不完整/空文本
修复步骤
1. 修正CSVReader的Read方法(处理BOM和通用换行)
修改接收字符串的Read方法,添加BOM移除逻辑,替换更通用的换行分割正则:
using UnityEngine; using System; using System.Collections.Generic; using System.Text.RegularExpressions; public class CSVReader { static string SPLIT_RE = @",(?=(?:[^"]*"[^"]*")*(?![^"]*"))"; static char[] TRIM_CHARS = { '"' }; // 保留原Resources加载方法(可选) public static List<Dictionary<string, object>> Read(string file) { TextAsset data = Resources.Load(file) as TextAsset; return Read(data.text); // 复用字符串版核心逻辑 } // 处理字符串的核心方法 public static List<Dictionary<string, object>> Read(string data) { var list = new List<Dictionary<string, object>>(); // 移除UTF-8 BOM头(部分CSV保存时会自动添加) if (!string.IsNullOrEmpty(data) && data[0] == '\ufeff') { data = data.Substring(1); } // 匹配所有平台换行符:Windows(\r\n)、Linux(\n)、Mac(\r) var lines = Regex.Split(data, @"\r?\n|\r"); if (lines.Length <= 1) return list; var header = Regex.Split(lines[0], SPLIT_RE); // 清理表头的空白和多余引号 for (int j = 0; j < header.Length; j++) { header[j] = header[j].Trim().Trim(TRIM_CHARS); } for (var i = 1; i < lines.Length; i++) { var line = lines[i].Trim(); if (string.IsNullOrEmpty(line)) continue; var values = Regex.Split(line, SPLIT_RE); if (values.Length == 0) continue; var entry = new Dictionary<string, object>(); for (var j = 0; j < header.Length && j < values.Length; j++) { string value = values[j]; value = value.TrimStart(TRIM_CHARS).TrimEnd(TRIM_CHARS).Replace("\\", ""); object finalvalue = value; int n; float f; if (int.TryParse(value, out n)) { finalvalue = n; } else if (float.TryParse(value, out f)) { finalvalue = f; } entry[header[j]] = finalvalue; } list.Add(entry); } return list; } }
2. 修正LoadExcel的加载逻辑(使用协程+编码设置)
确保加载方法是协程,等待下载完成,并指定UTF-8编码:
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; public class LoadExcel : MonoBehaviour { void Start() { // 必须用协程启动异步加载流程 StartCoroutine(LoadItemData()); } IEnumerator LoadItemData() { string path = Path.Combine(Application.streamingAssetsPath, "MyExcel.csv"); UnityWebRequest uwr = UnityWebRequest.Get(path); // 强制指定UTF-8编码,避免乱码问题 uwr.downloadHandler = new DownloadHandlerBuffer(); uwr.downloadHandler.textEncoding = System.Text.Encoding.UTF8; yield return uwr.SendWebRequest(); // 错误处理,快速定位加载失败原因 if (uwr.result != UnityWebRequest.Result.Success) { Debug.LogError("CSV加载失败: " + uwr.error); yield break; } List<Dictionary<string, object>> data = CSVReader.Read(uwr.downloadHandler.text); // 可选:打印表头验证是否包含ID字段 if (data.Count > 0) { Debug.Log("表头字段列表:"); foreach (var key in data[0].Keys) { Debug.Log("- " + key); } } } }
关键说明
- BOM处理:Excel导出的CSV常带UTF-8 BOM,直接读取会导致表头第一个字段前附加
\ufeff(如\ufeffID),自然无法匹配"ID"字段。 - 换行正则:原代码的换行正则写法存在显示异常,替换为
\r?\n|\r可兼容所有平台的换行格式。 - 协程必要性:UnityWebRequest是异步操作,必须用
yield return等待下载完成,否则会读取到空或不完整的文本。
内容的提问来源于stack exchange,提问作者Yidi
相关产品推荐
相关产品推荐

