如何获取带指定Tag的所有GameObject顶点坐标并保存为JSON文件
批量获取指定Tag对象顶点并保存为JSON解决方案
核心思路
- 用
GameObject.FindGameObjectsWithTag("wallTag")批量获取所有目标对象 - 遍历每个对象,提取Mesh(兼容MeshFilter和SkinnedMeshRenderer组件)
- 将顶点坐标(可选转换为世界坐标)整理为可序列化的数据结构
- 借助Unity的
JsonUtility完成数据序列化,再写入本地文件
完整代码实现
using UnityEngine; using System.IO; using System.Collections.Generic; // 单个墙体的顶点数据结构 [System.Serializable] public class WallVertexData { public string objectName; public List<Vector3Data> vertices; } // 用于序列化Vector3,让JSON结构更简洁 [System.Serializable] public class Vector3Data { public float x; public float y; public float z; public Vector3Data(Vector3 vec) { x = vec.x; y = vec.y; z = vec.z; } } // 所有墙体数据的集合容器 [System.Serializable] public class WallCollectionData { public List<WallVertexData> allWalls; } public class WallVertexExporter : MonoBehaviour { public void ExportWallVerticesToJson() { // 1. 获取所有带目标Tag的对象 GameObject[] wallObjects = GameObject.FindGameObjectsWithTag("wallTag"); if (wallObjects.Length == 0) { Debug.LogWarning("未找到带wallTag的GameObject"); return; } WallCollectionData collection = new WallCollectionData(); collection.allWalls = new List<WallVertexData>(); // 2. 遍历每个对象提取顶点数据 foreach (GameObject wallObj in wallObjects) { Mesh targetMesh = null; // 优先读取MeshFilter的Mesh MeshFilter meshFilter = wallObj.GetComponent<MeshFilter>(); if (meshFilter != null) { targetMesh = meshFilter.mesh; } // 兼容蒙皮网格对象 else { SkinnedMeshRenderer skinnedRenderer = wallObj.GetComponent<SkinnedMeshRenderer>(); if (skinnedRenderer != null) { targetMesh = skinnedRenderer.sharedMesh; } } if (targetMesh == null) { Debug.LogWarning($"{wallObj.name} 缺少MeshFilter或SkinnedMeshRenderer组件,已跳过"); continue; } WallVertexData wallData = new WallVertexData(); wallData.objectName = wallObj.name; wallData.vertices = new List<Vector3Data>(); // 转换顶点为世界坐标(若需局部坐标,直接用targetMesh.vertices即可) Vector3[] localVertices = targetMesh.vertices; foreach (Vector3 localVec in localVertices) { Vector3 worldVec = wallObj.transform.TransformPoint(localVec); wallData.vertices.Add(new Vector3Data(worldVec)); } collection.allWalls.Add(wallData); } // 3. 序列化为格式化后的JSON字符串 string jsonContent = JsonUtility.ToJson(collection, true); // 4. 保存到持久化路径,跨平台兼容 string savePath = Path.Combine(Application.persistentDataPath, "WallVertices.json"); File.WriteAllText(savePath, jsonContent); Debug.Log($"顶点数据已保存至: {savePath}"); } // 编辑器菜单快捷入口,无需挂载脚本即可测试 [UnityEditor.MenuItem("Tools/导出墙体顶点数据")] private static void TriggerExport() { GameObject tempObj = new GameObject("TempExporter"); tempObj.AddComponent<WallVertexExporter>().ExportWallVerticesToJson(); DestroyImmediate(tempObj); } }
关键细节说明
- 坐标转换:代码默认输出世界坐标,若需局部坐标,直接替换
wallObj.transform.TransformPoint(localVec)为localVec即可 - 序列化要求:所有自定义数据类必须添加
[System.Serializable]标签,否则JsonUtility无法识别 - 路径选择:使用
Application.persistentDataPath确保在Windows、Mac、移动端都能正常写入文件,也可自行修改为自定义路径(注意权限限制) - 异常防护:加入了组件空值判断,避免因对象缺少Mesh组件导致运行报错
测试步骤
- 将脚本放入Unity项目的Assets目录
- 顶部菜单点击
Tools/导出墙体顶点数据 - 在控制台查看文件保存路径,打开生成的
WallVertices.json即可查看数据
内容的提问来源于stack exchange,提问作者JuanSB
相关产品推荐
相关产品推荐

