unity开发遇到的几个坑(UGUI等)

最近开始研究unity,准备将之前自己业余时间做的一款游戏(金庸群侠传X)发行移动端版本(我不是游戏公司从业人员,业余时间自己做着玩,大神轻喷)。由于之前使用silverlight(C#)做的,所以移植unity有天然的语言优势。

看了一下unity的更新公告,4.6出的UGUI我比较喜欢,因为之前也用过NGUI,总感觉不是很顺畅。那么,即使有坑,我们也来趟趟吧。


到现在陆陆续续大概已经趟了一个月的坑了,总的感觉是,对于unity还是比较满意的:非常简单容易上手,功能还算齐全——现在DEMO版本已经能够在android、ios上较好的运行。上两张截图吧


unity开发遇到的几个坑(UGUI等)_第1张图片

unity开发遇到的几个坑(UGUI等)_第2张图片

unity开发遇到的几个坑(UGUI等)_第3张图片


现在总结一下我在开发中碰到的几个“坑”——当然,话说在前头,因为我也是刚开始学习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开发遇到的几个坑(UGUI等)_第4张图片

我手动在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的话,有时就会出现动画状态错乱。我的状态机是这样的:

unity开发遇到的几个坑(UGUI等)_第5张图片

所以我代码里现在是每次需要等待一段时间后,再进行切换。。


4、sprite editor中的BUG

在sprite editor中通过鼠标调整锚点为custom,第一次保存(这时候unity已经自动将类型切换为custom了)会失败!需要保存两次——但是第二次必须又和第一次不是同一个锚点,否则保存按钮点不下去!

或者先手动将锚点类型改为custom,然后再保存才可以。



好了,吐槽了这么多问题,总之unity新版本我还是很支持的。毕竟原生态的GUI系统还是比NGUI等硬往上“套”的UI系统要好很多。对于unity3d使用C#编程语言也是更加好顶赞。我不是一个喜欢讨论哪个编程语言好的人,就我来说,我至少使用过10多种语言编写过代码,目前来说感觉比较酸爽的还是C#。

你可能感兴趣的:(unity开发遇到的几个坑(UGUI等))