2015-05-05 116 views
0

我正在使用字典來存儲網格點,並且我不希望爲每個網格點顯示Handle,因爲3個點共享相同的Vector3位置,所以我正在存儲指向字典,然後檢查字典以查看該值是否存在,如果不添加句柄並將該點添加到字典中,則只需將該點添加到字典中,而不是創建額外的句柄。Dictionary ContainsValue()導致程序停止響應

當我運行此,編輯器停止響應,我必須做強制退出,並導致該問題的是我if聲明。如果我評論它是否正常工作。如果我只是添加所有句柄並且使用「否」,它也可以工作,但由於所有句柄,它運行緩慢。

網格有大約23k個頂點。我可以做些什麼來優化這個?

public void OnSceneGUI(){ 
    Creator t = (Creator)target; 
    Mesh mesh = t.GetComponent<MeshFilter>().sharedMesh; 
    if (mesh != null) { 
     Vector3[] vertices = mesh.vertices; 

     Vector3 lp = t.transform.position; 
     Handles.color = Color.red; 
     Dictionary<int, Vector3> dict = new Dictionary<int, Vector3>(); 
     int i = 0; 
     foreach (Vector3 v in vertices) { 
      Vector3 p = lp - v; 
      Vector3 pos = new Vector3 (p.x, -p.z, p.y); 

      if(dict.ContainsValue(pos)){ 
       Handles.FreeMoveHandle(pos, Quaternion.identity, 0.001f, Vector3.zero, Handles.DotCap); 
      } 

      dict.Add (i, pos); 
      i++; 

     } 
    } 
} 

回答

4

您在這兒濫用Dictionary

  • ContainsValue不得不枚舉整個字典只是爲了知道給定的值是否在裏面。這是因爲字典索引密鑰,而不是。這是一個O(n)操作。

  • 而你只有Add項目的字典,沒有使用的鍵,那麼你只是放下字典,不要用於其他任何東西。您沒有使用映射功能,該功能已針對字典進行了優化。

嘗試用HashSet代替:

var handles = new HashSet<Vector3>(); 

foreach (Vector3 v in vertices) { 
    Vector3 p = lp - v; 
    Vector3 pos = new Vector3 (p.x, -p.z, p.y); 

    if (!handles.Add(pos)) { 
     Handles.FreeMoveHandle(pos, Quaternion.identity, 0.001f, Vector3.zero, Handles.DotCap); 
    } 
} 

HashSetAdd方法返回一個bool告訴你,如果加入(true)的值,或者如果它已經在集合存在(false )。

+0

它現在不再掛起,但它不放置所有的頂點 –

+1

我想這是由於浮點精度問題(你不應該比較浮點值嚴格相等)。你可以檢查嗎?如果這是由於這個原因,你可以嘗試''添加'略微圓形的座標向量''處理'集合,這可能* *給預期的結果,但也可能導致一些點丟失。在這種情況下,真正的解決方案是使用類似八叉樹而不是簡單的'HashSet'。 –

相關問題