2015-05-04 26 views
1

這是將objs導入到我的團結中的代碼。爲什麼我的團結在導入obj時掛起?

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); 
    } 
} 

當模型加載時,進度條應該平穩運行。 但是,由於加載了modeland,導致Unity無法看到該欄的進度。 任何人都知道如何延遲進度條的繪製,以便看到它。

回答

0

Unity掛起的原因是因爲Unity(主要)運行在單個線程上,意味着Update中的ImportFile函數將在下一行代碼被調用之前完全完成,這將阻止OnGUI函數被調用,直到整個更新功能已完成。

解決此問題的唯一方法是使用MultiThreading,因爲您無法在主線程之外訪問Unity的任何數據,因此您只能在單獨的線程中訪問自己的數據。

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

看起來像原來的網站已關閉,但這確實在Unity解釋線程的一個很好的工作,我和附帶了一些示例代碼和使用情況