1. 程式人生 > >unity開發遇到的幾個坑(UGUI等)

unity開發遇到的幾個坑(UGUI等)

最近開始研究unity,準備將之前自己業餘時間做的一款遊戲(金庸群俠傳X)發行移動端版本(我不是遊戲公司從業人員,業餘時間自己做著玩,大神輕噴)。由於之前使用silverlight(C#)做的,所以移植unity有天然的語言優勢。

看了一下unity的更新公告,4.6出的UGUI我比較喜歡,因為之前也用過NGUI,總感覺不是很順暢。那麼,即使有坑,我們也來趟趟吧。

到現在陸陸續續大概已經趟了一個月的坑了,總的感覺是,對於unity還是比較滿意的:非常簡單容易上手,功能還算齊全——現在DEMO版本已經能夠在android、ios上較好的執行。上兩張截圖吧




現在總結一下我在開發中碰到的幾個“坑”——當然,話說在前頭,因為我也是剛開始學習unity,目前我自己認為的坑也可能是我自己的理解不夠,如果大家有更好的解決方法,歡迎指正!樓主寫這篇部落格的時候是2015年1月13日,使用的是當前最新的unity 4.6f1版本。

1、scroll rect的各種問題

(2015年02月9日:這個是我自己搞錯了,unity有提供方法,只是我之前用錯了,請移步這篇博文,這一條下面寫的大家就當看個笑話吧 :D)

很多介面需要用到滾屏,unity提供scroll rect控制元件。具體的組織方式為:

每個ScrollRect對應一個scrollcontent,ScrollContent定義內容的排版組織方式,如Grid Layout Group或者Vertical Layout Group。(這裡比較像silverlight中的StackPanel和GridPanel)

我使用以後發現一個最大的問題是,scroll content無法根據其包含的內容自動伸縮

。也就是說,scroll content的寬和高需要手動指定,如果其中內容超出了它的範圍,那麼超出的內容將無法滾屏過去。

這一點實在是把我噁心到爆了,於是出現了諸如以下的程式碼

        if (Mode == SelectMenuMode.Vertical)
        {
            selectContent.GetComponent<VerticalLayoutGroup>().enabled = true;
            selectContent.GetComponent<GridLayoutGroup>().enabled = false;

            float spacing = selectContent.GetComponent<VerticalLayoutGroup>().spacing;
            //by cg:
            //unity每次需要手動設定scroll content的大小
            float height = spacing;
            foreach (Transform s in selectContent)
            {
                height += s.GetComponent<RectTransform>().rect.height - spacing;
            }

            float width = selectContent.GetComponent<RectTransform>().rect.width;
            selectContent.GetComponent<RectTransform>().sizeDelta = new Vector2(width, height);
            
        }
        else if (Mode == SelectMenuMode.Grid)
        {
            selectContent.GetComponent<VerticalLayoutGroup>().enabled = false;
            selectContent.GetComponent<GridLayoutGroup>().enabled = true;

            float cellX = selectContent.GetComponent<GridLayoutGroup>().cellSize.x;
            float cellY = selectContent.GetComponent<GridLayoutGroup>().cellSize.y;
            float spacingX = selectContent.GetComponent<GridLayoutGroup>().spacing.x;
            float spacingY = selectContent.GetComponent<GridLayoutGroup>().spacing.y;
            float width = selectContent.GetComponent<RectTransform>().rect.width;
            float height = Mathf.CeilToInt(selectContent.childCount / (width / (cellX + spacingX))) * (cellY + spacingY);
            selectContent.GetComponent<RectTransform>().sizeDelta = new Vector2(width, height);
        }

每次需要手動去設定scroll Content的RectTranform的sizeDelta屬性。這樣程式碼很醜陋且極其不靈活。如果對於內容的寬高和排列可以預期,那還好。假如內容是一個文字,那豈不是還要算字型所佔寬高、行間距等等…… 

其次的一個問題是:scroll content的position設定貌似是有BUG。

為了實現大地圖滑動滾屏的效果,我將大地圖放到一個scroll content中,然後可以由玩家手指滑動來進行拖拽,這個unity實現都沒有問題。問題是,我需要由程式碼實現“滾屏”到某個點,則問題來了——


我手動在unity editor的執行時態設定的scoll content的x,y都是OK的,放到程式碼裡去設定transform.localPosition,就完全錯位了。

最後經過反覆嘗試,程式碼寫成了這樣……

<span style="white-space:pre">	</span>//大地圖卷屏
        if(location.name.Equals(RuntimeData.Instance.GetLocation(RuntimeData.Instance.CurrentBigMap)))
        {
            float x = -location.X + 640; //減去半個螢幕寬度,居中
            float y = -location.Y - 320; //減去半個螢幕高度,居中
            if (x < -1140) x = -1140; //邊界限制
            if (y > 640) y = 640;
            if (x > 0) x = 0;
            if (y < 0) y = 0;
            //by cg: 這裡對齊的邏輯有點奇怪,應該是unity的BUG,沒處理好對齊錨點。先手動修正。
            BigMap.transform.localPosition = new Vector3(-570f + x, 320f + y, 0);
        }

原因應該是我將scroll content的Anchor Pivot設定成了(0,1),但unity設定localPosition卻沒有寫參考這個錨點的邏輯,需要手動修正。

還有比較大的一個問題,ScrollRect所在的GameObject的Image元件,alpha設定有個BUG

按道理來說,這個Image只是scrollRect的一個背景,不影響其內容。但在把alpha設定到特別小的時候,不管是在editor上還是在執行環境中,scroll content都將顯示不出來。我試了大概是設到4-8以下就會完蛋。。所以我們需要獲得一個背景透明的scroll content,還不能把背景設定得太過於透明瞭……

2、LINQ不能在IOS上使用

在PC、EDITOR、MAC、ANDROID都沒有問題的程式碼,放到IOS真機(IPHONE、IPAD)上出問題。原因搜了一下大概意思應該是蘋果不允許出現動態程式碼。

這個是unity一直的問題了,貌似有辦法通過第三方的LINQ實現來保證。總之我是放棄使用LINQ了。

3、unity新版動畫系統Mecanim使用中碰到的問題

我的遊戲中人物分幾種動畫,如 站立、移動、攻擊。我使用Mecanim的狀態機來實現,動畫之間使用SetTrigger來實現切換。

我發現一個動畫在切換後如果沒有播放完畢,再呼叫SetTrigger的話,有時就會出現動畫狀態錯亂。我的狀態機是這樣的:


所以我程式碼裡現在是每次需要等待一段時間後,再進行切換。。

4、sprite editor中的BUG

在sprite editor中通過滑鼠調整錨點為custom,第一次儲存(這時候unity已經自動將型別切換為custom了)會失敗!需要儲存兩次——但是第二次必須又和第一次不是同一個錨點,否則儲存按鈕點不下去!

或者先手動將錨點型別改為custom,然後再儲存才可以。

好了,吐槽了這麼多問題,總之unity新版本我還是很支援的。畢竟原生態的GUI系統還是比NGUI等硬往上“套”的UI系統要好很多。對於unity3d使用C#程式語言也是更加好頂贊。我不是一個喜歡討論哪個程式語言好的人,就我來說,我至少使用過10多種語言編寫過程式碼,目前來說感覺比較酸爽的還是C#。