导入obj时为什么我的团结会挂起?

时间:2015-05-04 07:13:19

标签: c# unity3d unityscript

这是将objs导入我的团结的代码。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;

public class ObjImporter : MonoBehaviour {

    public GameObject spawnPoint;
    public GameObject emptyPrefabWithMeshRenderer;
    public string meshPath;
    public GameObject spawnedPrefab;

    static float progressPercentageMin;
    static float progressPercentageMax;
    static float progressPercentage;

    public Texture2D barBG;
    public Texture2D barLoad;

    int noOfLines;

    void Start ()
    {
        progressPercentageMin = 0;
        progressPercentageMax = 0;
        progressPercentage = 0;
    }

    void Update ()
    {
        progressPercentage = Mathf.Lerp (progressPercentageMin, progressPercentageMax, Time.time * progressPercentageMax * 0.01f);
        if(Input.GetKeyDown("space")){
            Mesh importedMesh = GetComponent<ObjImporter>().ImportFile(meshPath);
            noOfLines = TotalLines(meshPath);
            spawnedPrefab=Instantiate(emptyPrefabWithMeshRenderer,spawnPoint.transform.position,spawnPoint.transform.rotation) as GameObject;
            spawnedPrefab.GetComponent<MeshFilter>().mesh=importedMesh;
            spawnedPrefab.GetComponent<Renderer>().material.color = new Color(Random.value, Random.value, Random.value, 1.0f);
        }
    }

    public static void UpdateProgressBar()
    {
        progressPercentageMax += 10;
    }

    private struct meshStruct
    {
        public Vector3[] vertices;
        public Vector3[] normals;
        public Vector2[] uv;
        public Vector2[] uv1;
        public Vector2[] uv2;
        public int[] triangles;
        public int[] faceVerts;
        public int[] faceUVs;
        public Vector3[] faceData;
        public string name;
        public string fileName;
    }

    // Use this for initialization
    public Mesh ImportFile (string filePath){
        meshStruct newMesh = createMeshStruct(filePath);
        populateMeshStruct(ref newMesh);

        UpdateProgressBar();

        Vector3[] newVerts = new Vector3[newMesh.faceData.Length];
        Vector2[] newUVs = new Vector2[newMesh.faceData.Length];
        Vector3[] newNormals = new Vector3[newMesh.faceData.Length];
        int i = 0;
        /* The following foreach loops through the facedata and assigns the appropriate vertex, uv, or normal
         * for the appropriate Unity mesh array.
         */

        UpdateProgressBar();

        foreach (Vector3 v in newMesh.faceData)
        {
            newVerts[i] = newMesh.vertices[(int)v.x - 1];
            if (v.y >= 1)
                newUVs[i] = newMesh.uv[(int)v.y - 1];

            if (v.z >= 1)
                newNormals[i] = newMesh.normals[(int)v.z - 1];
            i++;
        }

        Mesh mesh = new Mesh();

        mesh.vertices = newVerts;
        mesh.uv = newUVs;
        mesh.normals = newNormals;
        mesh.triangles = newMesh.triangles;

        mesh.RecalculateBounds();
        mesh.Optimize ();

        UpdateProgressBar();

        return mesh;
    }

    private int TotalLines(string filePath)
    {
        using (StreamReader r = new StreamReader(filePath))
        {
            int i = 0;
            while (r.ReadLine() != null)
            {
                i++;
            }
            return i;
        }
    }

    private static meshStruct createMeshStruct(string filename)
    {
        int triangles = 0;
        int vertices = 0;
        int vt = 0;
        int vn = 0;
        int face = 0;
        meshStruct mesh = new meshStruct();
        mesh.fileName = filename;

        // Read and retrieve all the text in the file.
        StreamReader stream = File.OpenText(filename);
        string entireText = stream.ReadToEnd();
        stream.Close(); // End of stream.

        UpdateProgressBar();

        // Going through the retrieved text.
        using (StringReader reader = new StringReader(entireText))
        {
            string currentText = reader.ReadLine();
            char[] splitIdentifier = { ' ' };
            string[] brokenString;

            UpdateProgressBar();

            while (currentText != null)
            {
                if (!currentText.StartsWith("f ") && !currentText.StartsWith("v ") && !currentText.StartsWith("vt ")
                    && !currentText.StartsWith("vn "))
                {
                    currentText = reader.ReadLine();
                    if (currentText != null)
                    {
                        currentText = currentText.Replace("  ", " ");
                    }
                }
                else
                {
                    currentText = currentText.Trim();                           // Trim the current line
                    brokenString = currentText.Split(splitIdentifier, 50);      // Split the line into an array, separating the original line by blank spaces
                    switch (brokenString[0])
                    {
                    case "v":
                        vertices++;
                        break;
                    case   "vt":
                        vt++;
                        break;
                    case "vn":
                        vn++;
                        break;
                    case "f":
                        face = face + brokenString.Length - 1;
                        triangles = triangles + 3 * (brokenString.Length - 2); /*brokenString.Length is 3 or greater since a face must have at least
                                                                                     3 vertices.  For each additional vertice, there is an additional
                                                                                     triangle in the mesh (hence this formula).*/
                        break;
                    }
                    currentText = reader.ReadLine();
                    if (currentText != null)
                    {
                        currentText = currentText.Replace("  ", " ");
                    }
                }
            }
            UpdateProgressBar();
        }
        mesh.triangles = new int[triangles];
        mesh.vertices = new Vector3[vertices];
        mesh.uv = new Vector2[vt];
        mesh.normals = new Vector3[vn];
        mesh.faceData = new Vector3[face];

        UpdateProgressBar();

        return mesh;
    }

    private static void populateMeshStruct(ref meshStruct mesh)
    {
        StreamReader stream = File.OpenText(mesh.fileName);
        string entireText = stream.ReadToEnd();
        stream.Close();

        UpdateProgressBar();

        using (StringReader reader = new StringReader(entireText))
        {
            string currentText = reader.ReadLine();

            char[] splitIdentifier = { ' ' };
            char[] splitIdentifier2 = { '/' };
            string[] brokenString;
            string[] brokenBrokenString;
            int f = 0;
            int f2 = 0;
            int v = 0;
            int vn = 0;
            int vt = 0;
            int vt1 = 0;
            int vt2 = 0;

            UpdateProgressBar();

            while (currentText != null)
            {
                if (!currentText.StartsWith("f ") && !currentText.StartsWith("v ") && !currentText.StartsWith("vt ") &&
                    !currentText.StartsWith("vn ") && !currentText.StartsWith("g ") && !currentText.StartsWith("usemtl ") &&
                    !currentText.StartsWith("mtllib ") && !currentText.StartsWith("vt1 ") && !currentText.StartsWith("vt2 ") &&
                    !currentText.StartsWith("vc ") && !currentText.StartsWith("usemap "))
                {
                    currentText = reader.ReadLine();
                    if (currentText != null)
                    {
                        currentText = currentText.Replace("  ", " ");
                    }
                }
                else
                {
                    currentText = currentText.Trim();
                    brokenString = currentText.Split(splitIdentifier, 50);
                    switch (brokenString[0])
                    {
                    case "g":
                        break;
                    case "usemtl":
                        break;
                    case "usemap":
                        break;
                    case "mtllib":
                        break;
                        // 
                    case "v":
                        mesh.vertices[v] = new Vector3(System.Convert.ToSingle(brokenString[1]), System.Convert.ToSingle(brokenString[2]),
                                                       System.Convert.ToSingle(brokenString[3]));
                        v++;
                        break;
                    case "vt":
                        mesh.uv[vt] = new Vector2(System.Convert.ToSingle(brokenString[1]), System.Convert.ToSingle(brokenString[2]));
                        vt++;
                        break;
                    case "vt1":
                        mesh.uv[vt1] = new Vector2(System.Convert.ToSingle(brokenString[1]), System.Convert.ToSingle(brokenString[2]));
                        vt1++;
                        break;
                    case "vt2":
                        mesh.uv[vt2] = new Vector2(System.Convert.ToSingle(brokenString[1]), System.Convert.ToSingle(brokenString[2]));
                        vt2++;
                        break;
                    case "vn":
                        mesh.normals[vn] = new Vector3(System.Convert.ToSingle(brokenString[1]), System.Convert.ToSingle(brokenString[2]),
                                                       System.Convert.ToSingle(brokenString[3]));
                        vn++;
                        break;
                    case "vc":
                        break;
                    case "f":

                        int j = 1;
                        List<int> intArray = new List<int>();
                        while (j < brokenString.Length && ("" + brokenString[j]).Length > 0)
                        {
                            Vector3 temp = new Vector3();
                            brokenBrokenString = brokenString[j].Split(splitIdentifier2, 3);    //Separate the face into individual components (vert, uv, normal)
                            temp.x = System.Convert.ToInt32(brokenBrokenString[0]);
                            if (brokenBrokenString.Length > 1)                                  //Some .obj files skip UV and normal
                            {
                                if (brokenBrokenString[1] != "")                                    //Some .obj files skip the uv and not the normal
                                {
                                    temp.y = System.Convert.ToInt32(brokenBrokenString[1]);
                                }
                                temp.z = System.Convert.ToInt32(brokenBrokenString[2]);
                            }
                            j++;

                            mesh.faceData[f2] = temp;
                            intArray.Add(f2);
                            f2++;
                        }
                        j = 1;
                        while (j + 2 < brokenString.Length)     //Create triangles out of the face data.  There will generally be more than 1 triangle per face.
                        {
                            mesh.triangles[f] = intArray[0];
                            f++;
                            mesh.triangles[f] = intArray[j];
                            f++;
                            mesh.triangles[f] = intArray[j+1];
                            f++;

                            j++;
                        }
                        break;
                    }
                    currentText = reader.ReadLine();
                    if (currentText != null)
                    {
                        currentText = currentText.Replace("  ", " ");       //Some .obj files insert double spaces, this removes them.
                    }
                }
            }
        }
        UpdateProgressBar();
    }

    void OnGUI()
    {
        //GUI.Label (new Rect (20, 20, 100, 100), progressPercentage.ToString());
        GUI.DrawTexture(new Rect(100, 100, 100, 20), barBG); 
        GUI.DrawTexture(new Rect(100, 100, progressPercentage, 20), barLoad);
    }
}

加载模型时,进度条应该可以顺利运行。 但是,Unity由于加载了模式而挂起,你实际上无法看到条形图的进度。 任何人都知道如何延迟绘制进度条以便看到它。

1 个答案:

答案 0 :(得分:0)

Unity挂起的原因是Unity(大部分)在单个线程上运行,这意味着Update中的ImportFile函数将在下一行代码被调用之前完全完成,这将阻止OnGUI函数被调用直到整个更新功能已完成。

解决这个问题的唯一方法是使用MultiThreading,因为您无法访问主线程之外的任何Unity数据,因此在Unity中很难实现,因此您只能访问自己的数据在另一个线程中。

https://web.archive.org/web/20140702033426/http://unitygems.com/threads/

看起来原始网站已关闭,但这对我来说非常好地解释了Unity中的线程并附带了一些示例代码和用例