1. 程式人生 > >Unity3D —— 報錯解決方案和常用功能集

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;