Unity3D 报错解决方案及常用功能收集

发表于2017-09-29
评论0 3.2k浏览

1.在Dictionary迭代器进行修改:

  1. var _key = index2factionDic.Keys.GetEnumerator();  
  2. string item;  
  3. while (_key.MoveNext())  
  4. {  
  5.     item = index2factionDic[_key.Current];  
  6.     if (item.Equals(id))  
  7.     {  
  8.         tempDelete.Add(_key.Current);  
  9.         //index2factionDic.Remove(_key.Current);  
  10.     }  
  11. }  
此时会报错:
  1. InvalidOperationException: out of sync  
报错原因:

       在迭代过程中,Dictionary 变量及Value是只读的,C#有保护机制,不允许在这个过程中修改这些变量。

解决方案:

       创建一个列表List,来存储需要进行操作的key,然后在迭代器之外执行操作而不直接操作迭代器,便可解决报错问题:

  1. List<int> tempDelete = new List<int>();  
  2. //Index发生变化,移除旧的索引  
  3. if (index2factionDic.ContainsValue(id))  
  4. {  
  5.     var _key = index2factionDic.Keys.GetEnumerator();  
  6.     string item;  
  7.     while (_key.MoveNext())  
  8.     {  
  9.         item = index2factionDic[_key.Current];  
  10.         if (item.Equals(id))  
  11.         {  
  12.             tempDelete.Add(_key.Current);  
  13.             //index2factionDic.Remove(_key.Current);  
  14.         }  
  15.     }  
  16. }  
  17. for(int i = 0; i < tempDelete.Count; i )  
  18. {  
  19.     index2factionDic.Remove(tempDelete[i]);  
  20. }  
  21. tempDelete.Clear();  


2.UITable排序问题:

        一般将Item添加到UITable的子节点上之后,给每个Item取名,这里假设是在一个List循环中进行添加的,取名根据循环指针i来取,例如:

  1. //显示列表  
  2. for (int i = 0; i < cardlist.Count; i )  
  3. {  
  4.     nameStr = "card"   i;  
  5.     Transform itemtrans = cardTable.transform.Find(nameStr);  
  6.     if (itemtrans == null)  
  7.     {  
  8.         item = CreateOneCard(cardTable.transform);  
  9.     }  
  10.     else  
  11.     {  
  12.         item = itemtrans.gameObject;  
  13.         item.SetActive(true);  
  14.     }  
  15.     item.name = nameStr;  
  16. }  

        记得勾选UITable排序的Sorted选项:


        运行UITable.Reposition() 方法,会根据item的名称后面得序号来进行排序,但是有个问题,假如i大于10,如下图为生成后在Hierarchy中:


        这里我一行显示5个Item,按照正常顺序应该如下:

        结果出现了如下排序穿插


        原因:UITable在进行排序的时候,会从item命名字符串中取第一个数字来作为排序参考,所以“Card2”和“Card10”去到的第一个数字分别是“2”和“1”,所以“Card2”排到了“Card10”后面。

        解决方案:命名小于10的item进行修改,“Card2”改成"Card02",修改代码:

  1. //显示列表  
  2. for (int i = 0; i < cardlist.Count; i )  
  3. {  
  4.     if (i < 10)  
  5.     {  
  6.         nameStr = "card0"   i;  
  7.     }  
  8.     else  
  9.     {  
  10.         nameStr = "card"   i;  
  11.     }  
  12.     Transform itemtrans = cardTable.transform.Find(nameStr);  
  13.     if (itemtrans == null)  
  14.     {  
  15.         item = CreateOneCard(cardTable.transform);  
  16.     }  
  17.     else  
  18.     {  
  19.         item = itemtrans.gameObject;  
  20.         item.SetActive(true);  
  21.     }  
  22.     item.name = nameStr;  
  23. }  
        如此,排序的问题就解决了。


3.每次将预制拖到Hierachy窗口中就错:

NullReferenceException: Object reference not set to an instance of an object
PVPMatchPlayerScene..ctor ()
UnityEditorInternal.InternalEditorUtility:HierarchyWindowDrag(HierarchyProperty, Boolean, HierarchyDropMode)
UnityEditor.DockArea:OnGUI()


报错原因:大致原因是同一个UI预制中,物理碰撞框的数量太多,所以导致绘制报错,但不会影响功能

解决方案:对UI预制进行分割,减少单个Prefab的碰撞框数量,尽量降低UI预制的复杂度


4.NGUI中,使用UILabel,假如在创建诸如聊天输出窗口或者展示窗口,希望超出设定区域的内容,以省略号代替,可以使用一下方式来完成,前提是当前的NGUI版本的UILabel提供了Wrap这个接口。


5.修改粒子特效染色的简单方法:

  1. /// <summary>  
  2. /// 修改粒子特效染色  
  3. /// </summary>  
  4. /// <param name="gameObj"></param>  
  5. /// <param name="color"></param>  
  6. public static void SetParticleSystemToColor(GameObject gameObj, Color color)  
  7. {  
  8.     var partSyses = gameObj.GetComponentsInChildren<ParticleSystem>(true);  
  9.     foreach (ParticleSystem _partSys in partSyses)  
  10.     {  
  11.         _partSys.startColor = color;  
  12.     }  
  13. }  

6.修改Shader中的指定属性,例如Tint Color:


通过以下代码获取Mesh Renderer组件,然后设置对应的属性:

  1. MeshRenderer mesh_renders = gameObj.GetComponentsInChildren<MeshRenderer>();  
  2. mesh_renders.material.SetColor("_TintColor",selfcolor);  


7.在一个继承自MonoBehaviour的脚本中调用gameObject或者transform时,出现了如下错误:

NullReferenceException UnityEngine.Component.get_transform()”或者“NullReferenceException UnityEngine.Component.get_gameObject()”,可以先判断this是否为空再调用gameObject或者transform,如下:

  1. if (this == null || gameObject == null|| transform == null)  
  2. {  
  3.     return;  
  4. }  

8.用代码控制Unity编辑器的运行和暂停状态:

运行: UnityEditor.EditorApplication.isPlaying = true;

暂停:UnityEditor.EditorApplication.isPaused = true;

停止:UnityEditor.EditorApplication.isPlaying = false;

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引