Unity3D —— 報錯解決方案和常用功能集
1.在Dictionary迭代器進行修改:
此時會報錯:var _key = index2factionDic.Keys.GetEnumerator(); string item; while (_key.MoveNext()) { item = index2factionDic[_key.Current]; if (item.Equals(id)) { tempDelete.Add(_key.Current); //index2factionDic.Remove(_key.Current); } }
InvalidOperationException: out of sync
報錯原因: 在迭代過程中,Dictionary 變數及Value是隻讀的,C#有保護機制,不允許在這個過程中修改這些變數。
解決方案:
建立一個列表List,來儲存需要進行操作的key,然後在迭代器之外執行操作而不直接操作迭代器,便可解決報錯問題:
List<int> tempDelete = new List<int>(); //Index發生變化,移除舊的索引 if (index2factionDic.ContainsValue(id)) { var _key = index2factionDic.Keys.GetEnumerator(); string item; while (_key.MoveNext()) { item = index2factionDic[_key.Current]; if (item.Equals(id)) { tempDelete.Add(_key.Current); //index2factionDic.Remove(_key.Current); } } } for(int i = 0; i < tempDelete.Count; i++) { index2factionDic.Remove(tempDelete[i]); } tempDelete.Clear();
2.UITable排序問題:
一般將Item新增到UITable的子節點上之後,給每個Item取名,這裡假設是在一個List迴圈中進行新增的,取名根據迴圈指標i來取,例如:
//顯示列表 for (int i = 0; i < cardlist.Count; i++) { nameStr = "card" + i; Transform itemtrans = cardTable.transform.Find(nameStr); if (itemtrans == null) { item = CreateOneCard(cardTable.transform); } else { item = itemtrans.gameObject; item.SetActive(true); } item.name = nameStr; }
記得勾選UITable排序的Sorted選項:
執行UITable.Reposition() 方法,會根據item的名稱後面得序號來進行排序,但是有個問題,假如i大於10,如下圖為生成後在Hierarchy中:
這裡我一行顯示5個Item,按照正常順序應該如下:
結果出現瞭如下排序穿插:
原因:UITable在進行排序的時候,會從item命名字串中取第一個數字來作為排序參考,所以“Card2”和“Card10”去到的第一個數字分別是“2”和“1”,所以“Card2”排到了“Card10”後面。
解決方案:命名小於10的item進行修改,“Card2”改成"Card02",修改程式碼:
//顯示列表
for (int i = 0; i < cardlist.Count; i++)
{
if (i < 10)
{
nameStr = "card0" + i;
}
else
{
nameStr = "card" + i;
}
Transform itemtrans = cardTable.transform.Find(nameStr);
if (itemtrans == null)
{
item = CreateOneCard(cardTable.transform);
}
else
{
item = itemtrans.gameObject;
item.SetActive(true);
}
item.name = nameStr;
}
如此,排序的問題就解決了。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這個介面,教程:NGUI:UILabel用省略號替換超出顯示區域的內容
5.修改粒子特效染色的簡單方法:
/// <summary>
/// 修改粒子特效染色
/// </summary>
/// <param name="gameObj"></param>
/// <param name="color"></param>
public static void SetParticleSystemToColor(GameObject gameObj, Color color)
{
var partSyses = gameObj.GetComponentsInChildren<ParticleSystem>(true);
foreach (ParticleSystem _partSys in partSyses)
{
_partSys.startColor = color;
}
}
6.修改Shader中的指定屬性,例如Tint Color:
通過以下程式碼獲取Mesh Renderer元件,然後設定對應的屬性:
MeshRenderer mesh_renders = gameObj.GetComponentsInChildren<MeshRenderer>();
mesh_renders.material.SetColor("_TintColor",selfcolor);
7.在一個繼承自MonoBehaviour的指令碼中呼叫gameObject或者transform時,出現瞭如下錯誤:
“NullReferenceException UnityEngine.Component.get_transform()”或者“NullReferenceException UnityEngine.Component.get_gameObject()”,可以先判斷this是否為空再呼叫gameObject或者transform,如下:
if (this == null || gameObject == null|| transform == null)
{
return;
}
8.用程式碼控制Unity編輯器的執行和暫停狀態:
執行: UnityEditor.EditorApplication.isPlaying = true;
暫停:UnityEditor.EditorApplication.isPaused = true;
停止:UnityEditor.EditorApplication.isPlaying = false;