2015-05-05 79 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'。 –

相关问题