首页 > 代码库 > unity实现3D饼图

unity实现3D饼图

有一段时间没有玩过unity了,还是忙里偷闲捡起来折腾一下。最近升级到了4.6,新的版本加入了unity自带的unity系统,看起来清爽多了。在没有UGUI的日子里,有NGUI用用自然也是不错的,但好与坏都是相对的吧,相信unity官方做出来来的新的UI系统可以更加出色,方便易用。

对于新的UI系统,网上好多大牛都相继出了系列教程了,我暂时还没有太多精力来琢磨透。希望之后能够深入的研究一些东西,而不是浮于表面。总而言之,自己离大牛还有好几个身位,革命尚未成功,同志任需努力。

之前呢,就有用unity开发各种稀奇古怪小工具的想法,比如说制作3D图表之类的玩意,看起来就酷酷的哈。虽然说自我感觉执行力不差,但是有时候还是有点懒惰,无奈的研究生生活~~~昨天看到一哥们发了一篇制作3D图表的博客,利用LineRenderer绘制折线图,感觉还不错。于是就坚定了我写这篇博客的动力。

/*************************************分割线*************************************/

好吧,下面开始说正事。

先上图


首先呢,饼图其实就是将一个圆柱体按照比例分成若干个部分。每个部分都是一个扇形区域。

然后呢,我就把整个圆柱大致分成了100个如下图所示的三角形区域(实际上是立体的,这里姑且称这些三角形区域为一个基元)。

为什么说是大致100个部分呢,因为我们可能遇到某个扇页的占比有小数的情况,那么这种情况下,我会把有小数的区域分割成两块,各自计算占比,然后依据占比缩放。

之后,我们依据统计的数据,计算出这些数据之和,以及各扇页的占比,求得需要的的基元数目,以及各个基元的旋转角度,并对同一扇页内的基元加上相同的颜色。

最后,在各个扇页上方显示出占比。

基元:


若干扇区:




前面呢,说了实现的大致流程。整体实现起来是比较简单的,但是也遇到一些小问题。

1.unity自带的3D gameobject中是没有类似于基元的三明治形状的模型的。但我又不想去从外面倒入一个模型进来,于是干脆用代码生成一个好了。使用的方法比较笨,要自己设置网格的顶点和三角形。关键代码如下。

    /// <summary>
    /// 初始化网格
    /// </summary>
    void initMesh()
    {
        float y = Mathf.PI * Config.R / Config.NUM;
        float x = Mathf.Sqrt(Config.R * Config.R - y * y);
        Vector3 origin1 = new Vector3(0, 0, 0);
        Vector3 origin2 = new Vector3(x, 0, y);
        Vector3 origin3 = new Vector3(x, 0, -y);
        Vector3 offset = new Vector3(0, Config.HEIGHT, 0);

        mesh = new Mesh();
        mesh.vertices = new Vector3[6] { origin1 + offset, origin2 + offset, origin3 + offset, 
                                        origin1 - offset, origin2 - offset, origin3 - offset };

        mesh.triangles = new int[24] { 0,1,2,3,5,4,
                                0,3,2,2,3,5,
                                0,1,3,4,3,1, 
                                2,1,4,2,4,5};

        meshFilter = gameObject.AddComponent<MeshFilter>();
        meshFilter.mesh = mesh;

        meshRenderer = gameObject.AddComponent<MeshRenderer>();
        meshRenderer.material.shader = Shader.Find("Diffuse");
    }

2.因为我们这里每个基元都是1%,但有的扇页占据的比例可能会出现20.5%这样的数据,这样就需要做特殊处理。

    /// <summary>
    /// 创建一组fanbase
    /// 起始部分和结束部分特殊处理
    /// 因为可能不是整数,所以会有缩放
    /// </summary>
    private void initFanBaseList()
    {
        float beginCeil = Mathf.Ceil(begin);
        float endFloor = Mathf.Floor(end);

        createFanBase((beginCeil + begin) / 2-0.5f, beginCeil - begin);

        for (int i = (int)Mathf.Ceil(begin); i < (int)Mathf.Floor(end); i++)
        {
            createFanBase(i, 1f);
        }

        createFanBase((end + endFloor) / 2 - 0.5f, end - endFloor);
    }

3.最后一个小问题是,立体的文字显示,新版本的unity中,我已经找不到3D text了。

于是像下面这样,自己另外创建一个gameobject,加上TextMesh和MeshRenderer组件就可以显示立体的文字了。



总之,实现起来还是比较简单的。源代码保存在云盘中了,需要的朋友可以看看。(可能对旧版本有兼容问题)

http://pan.baidu.com/s/16g4nc


unity实现3D饼图