Unity自定义UI组件(十一) 雷达图、属性图

前言

借用梦想世界宠物属性图

Unity自定义UI组件(十一) 雷达图、属性图_第1张图片

想必大家都在游戏中见过属性图用于展示多种属性的数值,可以较为直观的对比某种属性的缺陷或者是哪种属性有优势。在三维可视化领域也会遇到类似的属性对比,用属性图来展示最为合适。

组件效果

  • 基础效果

Unity自定义UI组件(十一) 雷达图、属性图_第2张图片

  • 效果一

Unity自定义UI组件(十一) 雷达图、属性图_第3张图片

  • 效果二

Unity自定义UI组件(十一) 雷达图、属性图_第4张图片

  • 效果三

Unity自定义UI组件(十一) 雷达图、属性图_第5张图片

  • 效果四

Unity自定义UI组件(十一) 雷达图、属性图_第6张图片

  • 效果五

Unity自定义UI组件(十一) 雷达图、属性图_第7张图片

组件特点

  • 一键创建,无需额外资源
  • 超多属性可自定义
  • 可跟具需求拓展

主要内容

  • 组件实现(建造者模式)
  • 组件多样化(工厂模式)
  • 组件使用

详细讲解

组件实现(建造者模式)

建造者模式
  • 什么是建造者模式

建造者模式是设计模式的一种,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

属性图组件大致分为底图和线图两个层级,底图分为xy坐标轴和线框,线图可以分为线框和填充物,依据建造者模式的思想,我们可以分为四个部分去建造属性图,然后再统一组合展示。

建造者模式使用

我们利用接口将建造过程抽象,在实现了该接口的类的DrawRadar方法中将分布建造的内容组合起来。

  • 抽象接口
// 绘制基础
public interface IRadarBase 
{
    /// 绘制底图线框
    VertexHelper DrawBase( VertexHelper vh );
    /// 绘制xy坐标
    VertexHelper DrawAxis( VertexHelper vh );
}

// 绘制数据线段
public interface IRadarline 
{
    VertexHelper DrawLine( VertexHelper vh );
}

// 装配操作,将上述分布建造的内容合并
public interface IRadarFactory : IRadarBase , IRadarline
{
    VertexHelper DrawRadar( VertexHelper vh , Rect rect ,RadarBaseData radardata );  
}
  • 实现接口
// SpringGUIBase中提供一些公用的绘制方法,可继承或使用实例调用
public class BaseRadarFactory : SpringGUIBase, IRadarFactory
{
    public virtual VertexHelper DrawRadar( VertexHelper vh , Rect rect ,RadarBaseData radardata)
    {
        this.radarData = radardata;
        this.radarDatas = this.radarData.Getdata();
        this.size = rect.size;
        this.origin = new Vector2(-size.x / 2.0f , -size.y / 2.0f);
        // 依次调用不同的建造者,进行建造
        DrawBase(vh);
        DrawAxis(vh);
        DrawLine(vh);
        return vh;
    }
}

组件多样化(工厂模式)

通过上一篇 Unity自定义UI组件(十) 折线图中讲解工厂模式,所以在多样化操作中依旧使用工厂模式

工厂模式的使用
public class RadarFactory1 : BaseRadarFactory
{
    // 重写父类方法
    public override VertexHelper DrawBase(VertexHelper vh)
    {
        // 重新地图绘制部分,绘制另一种风格的底图
    }
}

public class RadarFactory2 : BaseRadarFactory
{
    // 重写父类方法
    public override VertexHelper DrawLine( VertexHelper vh )
    {
        // 绘制新的线条样式
    }
}

在客户端使用时,我们根据自己需要的类型构造对应的实例。如下:

// 雷达图绘制工厂
private IRadarFactory m_radarFactory
{
    get
    {
        // 获取对应实例,也可以利用反射的方法将其分装,进一步降低耦合使得新的模式的将入更加便捷,可以自己动手实现一下
        switch ( radarType )
        {
            case RadarType.Base:
                return new BaseRadarFactory();
            case RadarType.Type1:
                return new RadarFactory1();
            case RadarType.Type2:
                return new RadarFactory2();
            case RadarType.Type3:
                return new RadarFactory3();
            case RadarType.Type4:
                return new RadarFactory4();
            case RadarType.Type5:
                return new RadarFactory5();
        }
        return null;
    }
}

组件使用

数据输入

对于组件的开发和使用,我们需要明白一个观点,组件一定要有自己固定的数据格式,需要外界转化成对应的数据格式才可以使用,否则人人都将根据自己的需要求该组件的中的代码,而且随着组件的复杂度提升,修改的难度也大幅提升,不符合关闭修改,放开拓展的设计模式。因此需要一个代理/中介者来对数据进行处理并输出对应的数据格式。

  • 客户端输入

利用泛型运行更多类型的输入,方便数据的接入

public void Inject( IList datas )
{ 
    var radardata = RadarDataProxy.Convert2RD(datas);
    RadarBaseData.Adddata(radardata);   
    OnEnable();
}

public void Inject( IList[] datas )
{
    var radardatas = RadarDataProxy.Convert2RD(datas);
    RadarBaseData.Adddata(radardatas);
    OnEnable();
}
数据格式化
  • 代理处理数据格式

利用代理处理数据并返回固定格式,代理利用反射的方法,获取固定类型中某一个属性值或者是字段的值,根据自己的使用情况来做适当的调整。当然你也拓展其他适应自己项目的方法。

public class RadarDataProxy
{
    public static RadarData Convert2RD(IList datas)
    {
        RadarData data = new RadarData();
        Type type = typeof(T);
        PropertyInfo[] infos = type.GetProperties();
        foreach(var v in datas)
        {
            foreach (var info in infos)
            {
                if (info.Name.Equals("value"))
                    data.AddData((float)info.GetValue(v,null));
            } 
        }
        return data;
    }

    public static IList Convert2RD( IList[] datas )
    {
        IList result = new List();
        foreach (var data in datas)
            result.Add(Convert2RD(data));
        return result;
    }

    // 拓展适应自己项目的适配方法
}
具体使用
public class RMExampleData
{
    public float value{get;set;}

    public RMExampleData(float value)
    {
        this.value = value;
    }
}

IList radarthree = new List()
     {
         new RMExampleData(0.0f),
         new RMExampleData(0.1f),
         new RMExampleData(0.2f),
         new RMExampleData(0.3f),
         new RMExampleData(0.4f),
         new RMExampleData(0.5f),
         new RMExampleData(0.6f),
         new RMExampleData(0.7f),
         new RMExampleData(0.8f),
         new RMExampleData(0.9f),
         new RMExampleData(1f),
     };
RadarMap6.Inject(radarthree);
Inspector面板配置

Inspector面板没有重写所以开启来比较杂乱,自己配置一下就熟悉啦,再有不懂评论区留言或者是邮箱我。

  • Axis 部分是xy坐标,坐标是否显示箭头,箭头尺寸,颜色等。
  • base 部分是底板网格,半径,边数,是否显示内部网格,网格颜色,网格尺寸、网格层级等。
  • Layer 每个网格层级之间的颜色如果使用带颜色的模式一定要在此处配置,或者可能会出错。
  • LineColor 配置每一条线的颜色

Unity自定义UI组件(十一) 雷达图、属性图_第8张图片

更多使用的方法在实例代码中可以看到,实例代码在文章结尾。

后续拓展

  • SpringGUI中每个组件都是重新开发的基础方法用来绘制,我逐渐意识到我们可以将常用的方法封装起来作为以后的基类,加快绘制GUI的速度。
  • SpringGUI中的组件基本都不具有与输入设备交互的属性,我将会注重交互这个部分为后续的组件添加与输入设备交互的功能。

UGUI组件系列

  • Unity自定义UI组件(十) 折线图
  • Unity自定义UI组件(九) 颜色拾取器(下)
  • Unity自定义UI组件(八) 颜色拾取器(上)
  • Unity自定义UI组件(七)渐变工具、渐变色图片、渐变遮罩
  • Unity自定义UI组件(六)日历、日期拾取器
  • Unity自定义组件之(五) 目录树 UITree
  • Unity自定义UI组件(四)双击按钮、长按按钮
  • Unity自定义UI组件(三)饼图篇
  • Unity自定义UI组件(二)函数图篇(下)
  • Unity自定义UI组件(一)函数图篇(上)

Unity框架解读系列

  • [Unity]PureMVC框架解读(下)
  • [Unity]PureMVC框架解读(上)

分享地址(置顶目录包含所有组件的最新下载地址)

  • Github :https://github.com/ll4080333/UnityCodes
  • CSDN : http://blog.csdn.net/qq_29579137
  • 博客专栏 : http://blog.csdn.net/column/details/16329.html
  • QQ群 : 593906968 有什么不懂的可以加群咨询互相学习
    如果你想了解UGUI的更多拓展组件,欢迎关注我的博客,我会持续更新,支持一下我这个博客新手。如果以上文章对你有帮助,点个赞,让更多的人看到这篇文章,我们一起学习。如果有什么指点的地方欢迎在评论区留言,秒回复。

你可能感兴趣的:(unity3d,ui,自定义,Unity,UGUI,自定义UI组件)