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

前言

借用梦想世界宠物属性图

image

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

组件效果

  • 基础效果

这里写图片描述

  • 效果一

这里写图片描述

  • 效果二

这里写图片描述

  • 效果三

这里写图片描述

  • 效果四

这里写图片描述

  • 效果五

这里写图片描述

组件特点

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

主要内容

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

详细讲解

组件实现(建造者模式)
建造者模式

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

属性图组件大致分为底图和线图两个层级,底图分为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<T>( IList<T> datas )
{ 
    var radardata = RadarDataProxy.Convert2RD(datas);
    RadarBaseData.Adddata(radardata);   
    OnEnable();
}

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

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

public class RadarDataProxy
{
    public static RadarData Convert2RD<T>(IList<T> 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<RadarData> Convert2RD<T>( IList<T>[] datas )
    {
        IList<RadarData> result = new List<RadarData>();
        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<RMExampleData> radarthree = new List<RMExampleData>()
     {
         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 配置每一条线的颜色

这里写图片描述

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

后续拓展

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

UGUI组件系列

Unity框架解读系列

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

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值