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

Unity SolidGeometryLib初始化sgObject时空指针异常求助

问题:SolidGeometryLib自定义OBJ网格初始化空指针异常

我从Unity Asset Store购买了SolidGeometryLib插件用于项目中的网格布尔运算,尝试用加载自定义.obj文件的GameObject初始化sgObject时触发空指针异常,以下是我的实现代码:

void initGameObjectAsSGObject() {
        GameObject skullGameObject = GameObject.Find("Skull");
        Mesh mesh = skullGameObject.GetComponent<MeshFilter>().mesh;
        var verts = mesh.vertices;
        float[] vertices = new float[verts.Length * 3];
        Debug.Log(verts[0].x);
        foreach (Vector3 vertex in verts) {
            vertices.Append(vertex.x);
            vertices.Append(vertex.y);
            vertices.Append(vertex.z);
        }
        int[] triangles = mesh.triangles;
        Debug.Log(triangles[10]);
        // Skull
        IntPtr pnts = sg_array_create_points();
        for (int i = 0; i < vertices.Length; i += 3)
            sg_array_add_point(pnts, vertices[i], vertices[i + 1], vertices[i + 2]);
        IntPtr indxs = sg_array_create_int(); 
        for (int i = 0; i < triangles.Length; i++)
            sg_array_add_int(indxs, triangles[i]);
        
        IntPtr customMeshObj = sg_object_custom_mesh(pnts, indxs);
        Debug.Log(customMeshObj);
        if (customMeshObj == IntPtr.Zero)
        {
            Debug.Log("customMeshObj is null");
            return;
        }
        skullGameObject.AddComponent<sgObject>().InitObject(customMeshObj);
        skullGameObject.transform.parent = gameObject.transform;
        
        sg_array_free_points(pnts);
        sg_array_free_int(indxs);
    }

插件卖家提供的自定义网格创建示例代码:

public void AddCustomMesh()
        {
            float[] vertexes = {
             0.0f, 0.0f, 2.0f,                        //  v1
             1.788854f, 0.000000f, 0.894427f,         //  v2  
             0.552786f, 1.701302f, 0.894427f,         //  v3
             -1.447214f, 1.051462f, 0.894427f,        //  v4
             -1.447214f, -1.051462f, 0.894427f,       //  v5
             0.552786f, -1.701302f, 0.894427f,        //  v6
             1.447214f, 1.051462f, -0.894427f,        //  v7
             -0.552786f, 1.701302f ,-0.894427f,       //  v8
             -1.788854f, 0.000000f, -0.894427f,       //  v9
             -0.552786f, -1.701302f, -0.894427f,      //  v10
             1.447214f, -1.051462f, -0.894427f,       //  v11
             0.0f,       0.0f, -2.0f };               //  v12 

            int[] icosahedron_indexes = {
                 2, 0, 1,       //  triangle 1
                 3, 0, 2,       //  triangle 2
                 4, 0, 3,       //  triangle 3
                 5, 0, 4,       //  triangle 4
                 1, 0, 5,       //  triangle 5
                 2, 1, 6,       //  triangle 6
                 7, 2, 6,       //  triangle 7
                 3, 2, 7,       //  triangle 8
                 8, 3, 7,       //  triangle 9
                 4, 3, 8,       //  triangle 10
                 9, 4, 8,       //  triangle 11
                 5, 4, 9,       //  triangle 12
                 10, 5, 9,      //  triangle 13
                 6, 1, 10,      //  triangle 14
                 1, 5, 10,      //  triangle 15
                 6, 11, 7,      //  triangle 16
                 7, 11, 8,      //  triangle 17
                 8, 11, 9,      //  triangle 18
                 9, 11, 10,     //  triangle 19
                 10, 11, 6      //  triangle 20
             };


            GameObject cmO = new GameObject("CustomMesh");

            float randRad = UnityEngine.Random.Range(0.9f, 3.5f);

            IntPtr pnts = sg_array_create_points();
            for (int i = 0; i < vertexes.Length; i += 3)
                sg_array_add_point(pnts, vertexes[i] * randRad, vertexes[i + 1] * randRad, vertexes[i + 2] * randRad);

            IntPtr indxs = sg_array_create_int();
            for (int i = 0; i < icosahedron_indexes.Length; i++)
                sg_array_add_int(indxs, icosahedron_indexes[i]);

            IntPtr customMeshObj = sg_object_custom_mesh(pnts, indxs);

            sg_array_free_points(pnts);
            sg_array_free_int(indxs);

            if (customMeshObj == IntPtr.Zero)
            {
                DestroyImmediate(cmO);
                return;
            }

            randomTransform(customMeshObj);
            cmO.AddComponent<sgObject>().InitObject(customMeshObj);
            cmO.transform.parent = gameObject.transform;
        }

错误排查与修复

核心错误点

  1. 顶点数组填充逻辑错误
    你使用vertices.Append(vertex.x)填充数组,但Append方法不会修改原数组,而是返回一个包含新增元素的新数组,导致vertices始终是初始的全0数组。插件接收无效的顶点数据后无法生成有效网格,最终customMeshObj为IntPtr.Zero,后续调用InitObject触发空指针。

  2. 缺少空值检查
    未对skullGameObject、MeshFilter、mesh、triangles做空值判断,若GameObject找不到、缺少组件或网格数据为空,直接访问会触发空指针。

  3. 资源释放不完整
    当customMeshObj为空时,未释放已创建的pnts和indxs数组,会造成内存泄漏。

修正后的代码

void initGameObjectAsSGObject() {
    // 检查目标GameObject是否存在
    GameObject skullGameObject = GameObject.Find("Skull");
    if (skullGameObject == null) {
        Debug.LogError("找不到名为Skull的GameObject");
        return;
    }

    // 检查MeshFilter组件及Mesh是否有效
    MeshFilter meshFilter = skullGameObject.GetComponent<MeshFilter>();
    if (meshFilter == null || meshFilter.mesh == null) {
        Debug.LogError("Skull GameObject缺少MeshFilter组件或Mesh为空");
        return;
    }

    Mesh mesh = meshFilter.mesh;
    var verts = mesh.vertices;
    float[] vertices = new float[verts.Length * 3];
    
    // 正确填充顶点数组:通过索引直接赋值
    for (int i = 0; i < verts.Length; i++) {
        Vector3 vertex = verts[i];
        vertices[i * 3] = vertex.x;
        vertices[i * 3 + 1] = vertex.y;
        vertices[i * 3 + 2] = vertex.z;
    }

    // 检查三角形索引是否有效
    int[] triangles = mesh.triangles;
    if (triangles == null || triangles.Length == 0) {
        Debug.LogError("Mesh的三角形索引数组为空");
        return;
    }

    IntPtr pnts = sg_array_create_points();
    for (int i = 0; i < vertices.Length; i += 3)
        sg_array_add_point(pnts, vertices[i], vertices[i + 1], vertices[i + 2]);

    IntPtr indxs = sg_array_create_int(); 
    for (int i = 0; i < triangles.Length; i++)
        sg_array_add_int(indxs, triangles[i]);
    
    IntPtr customMeshObj = sg_object_custom_mesh(pnts, indxs);
    Debug.Log(customMeshObj);

    if (customMeshObj == IntPtr.Zero) {
        Debug.Log("customMeshObj is null");
        // 释放已创建的资源,避免内存泄漏
        sg_array_free_points(pnts);
        sg_array_free_int(indxs);
        return;
    }

    skullGameObject.AddComponent<sgObject>().InitObject(customMeshObj);
    skullGameObject.transform.parent = gameObject.transform;
    
    sg_array_free_points(pnts);
    sg_array_free_int(indxs);
}

额外注意事项

  • 若OBJ模型的顶点是世界空间坐标,需转换为GameObject的局部空间坐标(Unity的Mesh.vertices默认是局部空间),否则可能导致网格位置异常。
  • 确保OBJ模型的三角形索引是顺时针顺序,部分布尔运算插件对三角面的 winding order 有要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 19:24:55