You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取带指定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组件导致运行报错

测试步骤

  1. 将脚本放入Unity项目的Assets目录
  2. 顶部菜单点击Tools/导出墙体顶点数据
  3. 在控制台查看文件保存路径,打开生成的WallVertices.json即可查看数据

内容的提问来源于stack exchange,提问作者JuanSB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 21:21:01