Unity中如何从外部文件读取数据创建网格?
解析自定义地图语法并生成网格
首先,我们可以分步骤实现你的自定义语法解析,同时我也会给出一些更易维护的语法方案建议。
一、实现自定义语法解析
你的语法规则清晰明确:
[]代表网格的一行(对应y轴方向)()代表该行内的一个单元格(对应x轴方向)- 单元格内用
,分隔Celltype和Enemy,空的()代表无属性的空Cell
步骤1:预处理文本并提取行数据
读取TextAsset后,首先要提取所有[]包裹的行数据。这里提供两种实现方式,按需选择:
方式A:简单字符串分割(适合格式严格的文本)
private List<string> ExtractRows(string rawContent) { // 先移除所有冗余空格,避免格式空格干扰解析 string cleanedContent = rawContent.Replace(" ", ""); // 按[]分割,过滤空内容得到所有行的单元格串 return cleanedContent.Split(new[] { '[', ']' }, StringSplitOptions.RemoveEmptyEntries).ToList(); }
方式B:正则表达式匹配(更稳健,支持复杂文本场景)
using System.Text.RegularExpressions; private List<string> ExtractRows(string rawContent) { List<string> rowContents = new List<string>(); // 匹配所有[]包裹的内容,自动忽略无关字符 var rowMatches = Regex.Matches(rawContent, @"\[(.*?)\]"); foreach (Match match in rowMatches) { string rowContent = match.Groups[1].Value.Replace(" ", ""); if (!string.IsNullOrEmpty(rowContent)) { rowContents.Add(rowContent); } } return rowContents; }
步骤2:解析单元格并生成网格
拿到行数据后,就可以逐个解析单元格,生成Cell数组。这里假设Celltype和Enemy是枚举类型,如果是自定义类,可以替换为字典映射实例的逻辑:
private Cell[,] mapCells; private const int MaxGridSize = 10; // 保持你原本的10x10固定网格尺寸 private void ParseMap(string content) { List<string> rowContents = ExtractRows(content); if (rowContents.Count == 0) { Debug.LogWarning("No valid map rows found!"); return; } // 初始化10x10网格 mapCells = new Cell[MaxGridSize, MaxGridSize]; // 遍历每一行(y轴) for (int y = 0; y < Math.Min(rowContents.Count, MaxGridSize); y++) { string row = rowContents[y]; // 提取该行所有单元格的内容 var cellDatas = row.Split(new[] { '(', ')' }, StringSplitOptions.RemoveEmptyEntries); // 遍历该行的每个单元格(x轴) for (int x = 0; x < Math.Min(cellDatas.Length, MaxGridSize); x++) { string cellData = cellDatas[x]; Celltype type = null; Enemy enemy = null; if (!string.IsNullOrEmpty(cellData)) { // 分割Celltype和Enemy参数 var parts = cellData.Split(','); // 解析Celltype(枚举示例,类的话用字典映射) if (parts.Length >= 1 && Enum.TryParse(parts[0].Trim(), out Celltype parsedType)) { type = parsedType; } // 解析Enemy(枚举示例) if (parts.Length >= 2 && Enum.TryParse(parts[1].Trim(), out Enemy parsedEnemy)) { enemy = parsedEnemy; } } // 创建Cell并赋值到网格 mapCells[x, y] = new Cell(type, enemy); } // 补全行内不足10个的单元格为空白Cell for (int x = cellDatas.Length; x < MaxGridSize; x++) { mapCells[x, y] = new Cell(); } } // 补全不足10行的部分为空白行 for (int y = rowContents.Count; y < MaxGridSize; y++) { for (int x = 0; x < MaxGridSize; x++) { mapCells[x, y] = new Cell(); } } }
步骤3:整合读取与解析逻辑
把文件读取和解析流程结合起来:
private void LoadMap(string fileName) { TextAsset mapAsset = Resources.Load<TextAsset>($"Maps/{fileName}"); if (mapAsset == null) { Debug.LogError($"Failed to load map file: {fileName}"); return; } ParseMap(mapAsset.text); }
二、更优的外部文件语法建议
你的自定义语法虽可行,但可读性和可维护性不算突出,推荐几种更成熟的方案:
CSV格式:用逗号分隔单元格,空单元格留空,每行对应网格一行。示例:
forest,dragon, frost,dragon,,,frost,yeti death,giant,fire,goblin ,,,,,,解析逻辑极简,还能用Excel或普通文本编辑器快速编辑。
JSON格式:用二维数组直接映射网格,Unity可通过
JsonUtility或Newtonsoft Json直接序列化/反序列化,几乎无需手动解析。示例:[ ["forest,dragon", ""], ["frost,dragon", "", "", "frost,yeti"], ["death,giant", "fire,goblin"], ["", "", "", "", "", ""] ]甚至可以直接序列化
Cell对象数组,完全避免字符串分割的麻烦。TMX格式(Tiled地图编辑器):如果你的地图涉及图层、碰撞等复杂逻辑,推荐用Tiled Map Editor制作地图并导出TMX格式,Unity有现成插件(如Tiled2Unity)可直接导入,省去自行编写解析逻辑的工作量。
内容的提问来源于stack exchange,提问作者peterHasemann
相关产品推荐
相关产品推荐

