unity在UGUI界面上绘制曲线

这篇具有很好参考价值的文章主要介绍了unity在UGUI界面上绘制曲线。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

通过重写OnPopulateMesh方法,自定义顶点信息,实现曲线绘制,具体实现思路如下图所示:

        画一条线段,a 为起始点,b为终点,方向如蓝色箭头所示,由a指向b,黄色矩形框表示最终绘制的线段宽度,线段最终由四个顶点决定,这里分别记为a左、a右,b左,b右。

        想要计算线段的顶点坐标需要借助于法线方向,使向量ab与 vector3.forward形成一个平面,则  向量(a左,a右) 垂直于此平面,而 向量(a左,a右)的长度为曲线的宽度,设宽度为W,

则有:

               Vector3 normal = Vector3.Cross( (b-a).normalized,Vector3.forward).normalized;

a左 = a + normal*w/2;

a右 = a - normal*w/2;

b左 = b + normal*w/2;

b右 = b - normal*w/2;

unity ui曲线,unity,游戏引擎

一、实现基本绘制逻辑,使用鼠标全屏绘制

1、新建image,大小设置为全屏填充

unity ui曲线,unity,游戏引擎unity ui曲线,unity,游戏引擎

2、新建脚本 DrawCurveByMouse,脚本内容如下

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

public class DrawCurveByMouse : MaskableGraphic
{
    /// <summary>
    /// 存储整条线的所有顶点信息
    /// </summary>
    private List<UIVertex[]> vertexQuadList = new List<UIVertex[]>();

    protected override void OnPopulateMesh(VertexHelper vh)
    {
        base.OnPopulateMesh(vh);
        vh.Clear();
        for (int i = 0; i < vertexQuadList.Count; i++)
        {
            vh.AddUIVertexQuad(vertexQuadList[i]);
        }
    }

    /// <summary>
    /// 记录上一个点的坐标信息
    /// </summary>
    private Vector3 lastPoint;

    private Vector3 lastLeft;
    private Vector3 lastRight;

    /// <summary>
    /// 宽度
    /// </summary>
    public float halfWidth;

    public float smoothStep = 10;

    /// <summary>
    /// 是否为新曲线
    /// </summary>
    private bool isNewLine = false;


    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            isNewLine = true;
            lastPoint = ScreenPointToLocalPointInRectangle(Input.mousePosition);
        }

        if (Input.GetMouseButton(0))
        {
            DrawLine(ScreenPointToLocalPointInRectangle(Input.mousePosition));
        }
    }

    /// <summary>
    /// 屏幕左边转换为矩形框中的本地坐标
    /// </summary>
    private Vector3 ScreenPointToLocalPointInRectangle(Vector2 screenPoint)
    {
        Vector2 localPoint = Vector2.zero;
        switch (canvas.renderMode)
        {
            case RenderMode.WorldSpace:
                RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, canvas.worldCamera,
                    out localPoint);
                break;
            case RenderMode.ScreenSpaceCamera:
                RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, canvas.worldCamera,
                    out localPoint);
                break;
            case RenderMode.ScreenSpaceOverlay:
                RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, null,
                    out localPoint);
                break;
        }

        return localPoint;
    }

    private void DrawLine(Vector3 curr)
    {
        Vector3 dir = curr - lastPoint;
        if (dir.magnitude < smoothStep) return;

        Vector3 normal = Vector3.Cross(dir.normalized, Vector3.forward).normalized;
        if (isNewLine)
        {
            lastLeft = lastPoint + normal * halfWidth;
            lastRight = lastPoint - normal * halfWidth;
            isNewLine = false;
        }

        Vector3 currLeft = curr + normal * halfWidth;
        Vector3 currRight = curr - normal * halfWidth;


        // Vector3 currLeft = curr + dir.normalized*  width;
        // Vector3 currRight = curr - dir.normalized* width;

        UIVertex[] quad = new UIVertex[4];

        quad[0] = new UIVertex();
        quad[0].position = lastLeft;
        quad[0].color = color;


        quad[1] = new UIVertex();
        quad[1].position = lastRight;
        quad[1].color = color;


        quad[2] = new UIVertex();
        quad[2].position = currRight;
        quad[2].color = color;


        quad[3] = new UIVertex();
        quad[3].position = currLeft;
        quad[3].color = color;

        vertexQuadList.Add(quad);
        lastLeft = currLeft;
        lastRight = currRight;
        SetAllDirty();
    }
}

unity ui曲线,unity,游戏引擎unity ui曲线,unity,游戏引擎文章来源地址https://www.toymoban.com/news/detail-770261.html

二、将绘制范围限制到矩形中,仍使用鼠标绘制

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

/// <summary>
/// 在矩形框中绘制曲线
/// </summary>
public class DrawCurveInRect : MaskableGraphic, IPointerDownHandler, IPointerUpHandler, IPointerEnterHandler,
    IPointerExitHandler
{
    /// <summary>
    /// 存储整条线的所有顶点信息
    /// </summary>
    private List<UIVertex[]> vertexQuadList = new List<UIVertex[]>();

    protected override void OnPopulateMesh(VertexHelper vh)
    {
        base.OnPopulateMesh(vh);
        vh.Clear();
        for (int i = 0; i < vertexQuadList.Count; i++)
        {
            vh.AddUIVertexQuad(vertexQuadList[i]);
        }
    }

    /// <summary>
    /// 记录上一个点的坐标信息
    /// </summary>
    private Vector3 lastPoint;

    private Vector3 lastLeft;
    private Vector3 lastRight;

    /// <summary>
    /// 宽度
    /// </summary>
    public float halfWidth = 2;

    public float smoothStep = 10;

    /// <summary>
    /// 是否为新曲线
    /// </summary>
    private bool isNewLine = false;

    private bool isEnter = false;
    private bool isDrawing = false;

    private void Update()
    {
        if (isEnter && isDrawing)
        {
            DrawLine(ScreenPointToLocalPointInRectangle(Input.mousePosition));
        }
    }

    /// <summary>
    /// 屏幕左边转换为矩形框中的本地坐标
    /// </summary>
    private Vector3 ScreenPointToLocalPointInRectangle(Vector2 screenPoint)
    {
        Vector2 localPoint = Vector2.zero;
        switch (canvas.renderMode)
        {
            case RenderMode.WorldSpace:
                RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, canvas.worldCamera,
                    out localPoint);
                break;
            case RenderMode.ScreenSpaceCamera:
                RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, canvas.worldCamera,
                    out localPoint);
                break;
            case RenderMode.ScreenSpaceOverlay:
                RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, null,
                    out localPoint);
                break;
        }

        return localPoint;
    }

    private void DrawLine(Vector3 curr)
    {
        Vector3 dir = curr - lastPoint;
        if (dir.magnitude < smoothStep) return;

        Vector3 normal = Vector3.Cross(dir.normalized, Vector3.forward).normalized;
        if (isNewLine)
        {
            lastLeft = lastPoint + normal * halfWidth;
            lastRight = lastPoint - normal * halfWidth;
            isNewLine = false;
        }

        Vector3 currLeft = curr + normal * halfWidth;
        Vector3 currRight = curr - normal * halfWidth;


        // Vector3 currLeft = curr + dir.normalized*  width;
        // Vector3 currRight = curr - dir.normalized* width;

        UIVertex[] quad = new UIVertex[4];

        quad[0] = new UIVertex();
        quad[0].position = lastLeft;
        quad[0].color = color;


        quad[1] = new UIVertex();
        quad[1].position = lastRight;
        quad[1].color = color;


        quad[2] = new UIVertex();
        quad[2].position = currRight;
        quad[2].color = color;


        quad[3] = new UIVertex();
        quad[3].position = currLeft;
        quad[3].color = color;

        vertexQuadList.Add(quad);
        lastLeft = currLeft;
        lastRight = currRight;
        SetAllDirty();
    }

    public void OnPointerDown(PointerEventData eventData)
    {
        isNewLine = true;
        isDrawing = true;
        lastPoint = ScreenPointToLocalPointInRectangle(eventData.position);
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        isDrawing = false;
    }

    public void OnPointerEnter(PointerEventData eventData)
    {
        isEnter = true;
    }

    public void OnPointerExit(PointerEventData eventData)
    {
        isEnter = false;
        isDrawing = false;
    }
}

三、通过绘制函数曲线

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Serialization;
using UnityEngine.UI;

/// <summary>
/// 通过函数绘制曲线
/// </summary>
public class FunctionCurve : MaskableGraphic
{
    /// <summary>
    /// 存储整条线的所有顶点信息
    /// </summary>
    private List<UIVertex[]> curveQuads = new List<UIVertex[]>();

    [Header("X轴的取值范围,")] public Vector2 rangeX;
    [Header("Y轴的取值范围,")] public Vector2 rangeY;
    /// <summary>
    /// 宽度
    /// </summary>
    public float halfWidth = 2;
    [Header("控制曲线平滑度的步长")] public float smoothStep;
    private List<UIVertex[]> pointQuads = new List<UIVertex[]>();
    [Header("取样点的颜色")] public Color simpleColor;
    [Header("取样点在轴上的值")] public float[] simples;
    /// <summary>
    /// 宽度
    /// </summary>
    public float simpleHalfWidth = 2;
   

    protected override void OnPopulateMesh(VertexHelper vh)
    {
        base.OnPopulateMesh(vh);
        vh.Clear();
        for (int i = 0; i < curveQuads.Count; i++)
        {
            vh.AddUIVertexQuad(curveQuads[i]);
        }
        for (int i = 0; i < pointQuads.Count; i++)
        {
            vh.AddUIVertexQuad(pointQuads[i]);
        }
    }

    public List<UIVertex[]> CreatCurve()
    {
        List<UIVertex[]> vertexQuadList = new List<UIVertex[]>();
        //1、通过步长计算采样点数
        //限制步长,步长应大于单个像素代表的数值;
        float minStep = (rangeX.y - rangeX.x) / rectTransform.rect.width; //最小步长
        if (smoothStep < minStep)
        {
            smoothStep = minStep;
        }

        int count = (int)((rangeX.y - rangeX.x) / smoothStep); //采样数
        List<Vector2> points = new List<Vector2>();
        float x = 0;
        float y = 0;
        float x_rate = rectTransform.rect.width / (rangeX.y - rangeX.x);
        float y_rate = rectTransform.rect.height / (rangeY.y - rangeY.x);
        for (int i = 0; i < count; i++)
        {
            //2、计算每个采样点的值
            x = rangeX.x + smoothStep * i;
            y = GetY(x);
            //3、将采样点数值转换为坐标值
            points.Add(new Vector2(x * x_rate, y * y_rate));
        }


        for (int i = 1; i < count; i++)
        {
            if (points[i].y > rectTransform.rect.height) break;
            vertexQuadList.Add(GetQuad(points[i - 1], points[i]));
        }

        return vertexQuadList;
    }

    public List<UIVertex[]> CreatSimplePoints()
    {
        List<UIVertex[]> vertexQuadList = new List<UIVertex[]>();
        float x_rate = rectTransform.rect.width / (rangeX.y - rangeX.x);
        float y_rate = rectTransform.rect.height / (rangeY.y - rangeY.x);
        for (int i = 0; i < simples.Length; i++)
        {
            if (simples[i] >= rangeX.x && simples[i] <= rangeX.y)
            {
                vertexQuadList.Add(GetSimplePointQuad(new Vector2(simples[i] * x_rate, GetY(simples[i]) * y_rate)));
            }
        }

        return vertexQuadList;
    }

    private UIVertex[] GetQuad(Vector3 lastPoint, Vector3 curr)
    {
        Vector3 normal = Vector3.Cross((curr - lastPoint).normalized, Vector3.forward).normalized;

        Vector3 lastLeft = lastPoint + normal * halfWidth;
        Vector3 lastRight = lastPoint - normal * halfWidth;
        Vector3 currLeft = curr + normal * halfWidth;
        Vector3 currRight = curr - normal * halfWidth;

        UIVertex[] quad = new UIVertex[4];

        quad[0] = new UIVertex();
        quad[0].position = lastLeft;
        quad[0].color = color;


        quad[1] = new UIVertex();
        quad[1].position = lastRight;
        quad[1].color = color;


        quad[2] = new UIVertex();
        quad[2].position = currRight;
        quad[2].color = color;


        quad[3] = new UIVertex();
        quad[3].position = currLeft;
        quad[3].color = color;
        return quad;
    }

    private UIVertex[] GetSimplePointQuad(Vector3 point)
    {

        UIVertex[] quad = new UIVertex[4];

        quad[0] = new UIVertex();
        quad[0].position = point + new Vector3(-simpleHalfWidth, simpleHalfWidth);;
        quad[0].color = simpleColor;


        quad[1] = new UIVertex();
        quad[1].position = point + new Vector3(simpleHalfWidth, simpleHalfWidth);;
        quad[1].color = simpleColor;


        quad[2] = new UIVertex();
        quad[2].position = point + new Vector3(simpleHalfWidth, -simpleHalfWidth);;
        quad[2].color = simpleColor;


        quad[3] = new UIVertex();
        quad[3].position = point + new Vector3(-simpleHalfWidth, -simpleHalfWidth);;
        quad[3].color = simpleColor;
        return quad;
    }

    public float GetY(float x)
    {
        return Mathf.Pow(x, 2);
        return x;
    }

    [ContextMenu("Test")]
    public void Test()
    {
        curveQuads = CreatCurve();
        pointQuads = CreatSimplePoints();
        SetAllDirty();
    }
}

到了这里,关于unity在UGUI界面上绘制曲线的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【UGUI】学会Unity中UGUI中UI元素自适应问题

    彻底学会Unity中UGUI中UI元素自适应问题 官方介绍:设计用于多种分辨率的 UI - Unity 手册 所所谓自适应就是画面元素跟随屏幕分辨率的改变而保持相对位置或者自身像素同步改变! 屏幕分辨率自适应:依靠画布缩放器组件完成 相对位置:依靠锚点位置完成,锚点主要负责保持

    2024年02月04日
    浏览(39)
  • Unity(三)--导入3d模型并实现UGUI界面上嵌入3d模型

    Unity支持的常用模型格式及建模软件: 格式 建模软件 网格 动画 材质 骨骼 FBX 3DMax,C4D,Blender,Maya等 √ √ √ √ OBJ 3DMax,C4D,Blender,Maya等 √ 以FBX为例,将其拖入Assets中: 能看到对应对象的材质和组合都出现在这里 拖入对象中

    2024年02月07日
    浏览(40)
  • Unity--UGUI创建基本的UI

    随着UI系统的引入,已添加了新组件,这些组件将有助于创建特定于GUI的功能。其中一些元素包括文本,图像,按钮等。在本教程中,您将学习创建和使用基本UI。 通过Unity的用户界面(UI)系统,可以控制诸如:文本,图像,按钮和其他用户控件之类的元素,这些元素将为用

    2024年04月12日
    浏览(54)
  • Unity优化之UI篇(UGUI)

            在Unity中UI优化的核心问题就是重绘和批处理之间的平衡。虽然说可以通过一些简单的技巧单方面地减少批次或者减少重绘,但进行过一波优化之后,最终还是要面临批次和重绘的平衡问题。         Canvas是UGUI的基本组件,它生成表示放置在其上的 UI 元素的网

    2024年02月04日
    浏览(49)
  • Unity UGUI事件输入,点击UI无反应

    之前被一个特别低级的UI点击问题卡了好久,记录一下,避免之后再犯同样的错误。 UI事件输入未接受到的原因无非就几个,一一排查总能找到原因。 1、若是直接使用的unity组件中的按钮,但是点击按钮没有反应。         1)查找是否被其他UI遮挡         2)查找是否接收

    2024年04月13日
    浏览(50)
  • 【游戏开发解答】Unity中对UGUI的Image进行倾斜变形(UGUI | 精灵图 | OnPopulateMesh | 顶点偏移 | 变形)

    本文最终效果 一、前言 嗨,大家好,我是新发。 前同事问了我一个问题,如何将 UGUI 的 Image 进行变形,变成斜斜的, 最直接的就是出图的时候直接就画成斜的,我们不讨论这种情况,这里我们单纯的从技术实现上去思考能不能在 Unity 中通过 UGUI 的 Image 对图片进行倾斜变形

    2024年02月04日
    浏览(56)
  • Unity UGUI一键绑定UI控件工具(编辑器拓展)

    全为一键生成 实现自动生成代码绑定UI控件 并生成字典保存UI控件 减少自己拖拽 和手动书写过程 适用动态加载面板 建议搭配UI框架使用 根据当前选中的gameobject 查找其下方是否有对应类型的控件 有就保存到字典中 然后通过向上递归拼凑地址,然后生成到粘贴板 直接粘贴到目

    2024年04月23日
    浏览(62)
  • Unity3D学习之UI系统——UGUI

    3.2.1 Screen Space -Overlay 覆盖模式 3.2.2 Screen Space - Camera 摄像机模式 创建专门的摄像机渲染UI 并让主摄像机不渲染UI层 3.2.3 World Space 宽高 * 缩放系数 = UI界面大小 参考分辨率 图片格式要改为Sprite 恒定像素模式计算公式 会根据当前分辨率 和 参考分辨率的比率自动计算UI的缩放量

    2024年02月21日
    浏览(261)
  • Unity中UI方案。IMGUI、UIElement、UGUI、NGUI

    引言         unity中有很多ui方案,各种方案有什么优势劣势,这里一一列举一下,知识扩充一下。 UI方案 适用范围 IMGUI 仅用于Editor扩展,或运行时Debug UIElement 可用于发布运行时和Editor UGUI Runtime,两大主流 UI 解决方案之一 NGUI Runtime,两大主流 UI 解决方案之一,现已较少

    2024年02月09日
    浏览(54)
  • 【Unity之UI编程】如何用UGUI搭建一个登录注册面板

    👨‍💻个人主页 :@元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏 : UI_Unity专栏 🅰️ **** 逻辑:没有输入账号密码按下登录的时候打开提示面板,按下确定后返回并移除面板(淡入淡出效果显示) 逻辑:

    2024年01月23日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包