您当前的位置: 首页 >  编辑器

染指流年灬

暂无认证

  • 4浏览

    0关注

    194博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

UGUI进阶知识[二]自定义多边形image image精确点击以及 不继承monobehaviour的类如何在inspector显示自定义变量的编辑器知识

染指流年灬 发布时间:2019-11-08 21:31:58 ,浏览量:4

网上关于自制UIMask的博客也不少了 丢掉Mask遮罩,更好的圆形Image组件[Unity] 这里在自学了一部分之后详细记录一下 圆形遮罩的原理 以及 在自制mask里面实现精确点击的原理 以及 部分的编辑器知识 目前的UGUI有mask组件,但是存在一些缺点:

  • drawCall高,在一些CPU与GPU交互速率比较低的机器上,drawcall高是造成卡顿的一个主要因素
  • 边界锯齿感强 明显粗糙不好看
  • 点击不准确

自制UIMask涉及到的知识属于稍微底层了 代码的看通需要读者对渲染知识了解 图像的成型需要顶点和像素颜色的辅助,顶点简单来说就是帮助形成一个形状的各个端点,像素颜色是顶点内部每个像素点需要表达的颜色 圆形可以由若干个相同的以圆心为顶点的等腰三角面片组成正多边形,近似模拟出来。三角面片分得多了,多边形的边越多,夹角越大,就越近似圆形。

在比较多的时候 要实现一些看似比较复杂比较难上手的UI任务的时候 可以查看unity的UGUI 源码 ,unity对UGUI开源

Image的主要原理 在这里插入图片描述 上图大约的描述了 圆形遮罩的 生成过程 图中的0代表了中心顶点 举例 顶点2 的横坐标与圆心的差距x1是通过半径乘以角a的余弦值得到 纵坐标与圆心的差距y1通过半径乘以角a的正弦值得到,其他的顶点是类似的 (x1 + 0的x坐标, y1 + 0的y坐标)描述了顶点的坐标 全部顶点的生成顺序是按图中的1 2 3 4 这样逆时针生成的 0 1 2 三个顶点 组成了一个三角面片 但是 组合三角面片的顺序是 1 0 2 这样的一个方向 在图中按照这个方向连线可以发现是顺时针方向 如果降低周围顶点数量 就可以从圆形降低到多边形 顶点生成的顺序是按照阿拉伯数字递增来生成的 即图中的逆时针 然后加入到顶点数组的顺序也是按照这个来放置的 后面生成三角面的时候 传入AddTriangle的顶点顺序在图中是按照顺时针的 即1 0 2 和 2 0 3 这样 这是根据了unity的成像原理,生成三角面传入的顶点顺序在屏幕上看需要是 顺时针才会进行渲染 否则 会被引擎认为是背面 (模型内部往外看就是背面) 一般来说 背面一般不会进行渲染

如果一个方形的image里面 放了个内切圆 则如果没有点到圆的部分的话 unity引擎里面是会依然识别到点击的 所以要自己去弄精确点击的部分 精确点击的原理 一个点向右发出射线 因为任何自定义形状都是闭合的 所以如果穿过自定义形状的边的次数是偶数(偶数包括0) 则这个点一定在外边,否则 就是在里面了

下面的脚本挂载在UI组件下 同时再挂载一个button组件即可

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Sprites;
using UnityEngine.UI;

public class CircleImage : Image
{
   
    
    //图片被分成的总片数
    [SerializeField]
    protected int totalSegments = 100;
    //显示部分占圆形的百分比.
    [SerializeField]
    private float cdOutPercent = 1;
    private readonly Color32 GRAY_COLOR = new Color32(60, 60, 60, 255);
    private List imgVertexPosList;

    /// 
    /// 这个函数是image用于处理图像顶点的
    /// 重写这个方法可以定义顶点的处理过程
    /// 处理后的顶点要传回给VertexHelper
    /// 在c#里面 是不用加ref 和out 也能在被调用函数里面改变传进来的参数
    /// 使得调用函数的值不一样 具体百度
    /// 
    /// 
    protected override void OnPopulateMesh(VertexHelper vh)
    {
   
        //这里清除意义是不用unity内定的图片渲染顶点数据
        vh.Clear();

        imgVertexPosList = new List();

        GenVertex(vh, totalSegments);

        AddTriangle(vh, totalSegments);
    }

    private void GenVertex(VertexHelper vh, int segements)
    {
   
        float width = rectTransform.rect.width;
        float heigth = rectTransform.rect.height;
        int cdOutSegments = (int)(segements * cdOutPercent);

        //这里使用overrideSprite 因为使用Sprite的话 即使有赋值 有时会为空
        //DataUtility.GetOuterUV函数是获得图片的uv信息
        Vector4 uv = overrideSprite != null ? DataUtility.GetOuterUV(overrideSprite) : Vector4.zero;

        Debug.LogError("uv.x " + uv.x + " uv.y " + uv.y + " uv.z " + uv.z + " uv.w " + uv.w
关注
打赏
1665909078
查看更多评论
立即登录/注册

微信扫码登录

0.0449s