返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >Unity实现透视滑动列表
  • 426
分享到

Unity实现透视滑动列表

2024-04-02 19:04:59 426人浏览 八月长安
摘要

本文实例为大家分享了Unity实现透视滑动列表的具体代码,供大家参考,具体内容如下 1、目的 有时候,为了实现更好的美术效果,需要实现一些特殊的滑动列表,例如轨迹滑动,也有透视滑动。

本文实例为大家分享了Unity实现透视滑动列表的具体代码,供大家参考,具体内容如下

1、目的

有时候,为了实现更好的美术效果,需要实现一些特殊的滑动列表,例如轨迹滑动,也有透视滑动。
注意:本文里所展示的效果是未经测试的试验版,如果用于实际项目中,应该还需要优化代码和测试性能

2、思考

透视滑动列表可以有两种方式来实现:

第一种方法是,通过shader实现,其核心原理是,定义一个中心点坐标(CenterX,CenterY),再定义一个透视系数_ OffsetPerspective,在vert函数中,对于每个顶点,计算其偏移值,距离自己定义的中心点越远的顶点,其偏移值越大,简单概括就是距离中心点越远的顶点,就越把往中心点拉回去。实际算法就是:

OUT.worldPosition.x += (_CenterY + v.vertex.y - _OffsetX) / 1000 * (v.vertex.x - _CenterX) * _OffsetPerspective
这是我所使用的计算公式,其中,_OffsetX是自定义的偏移值,用于对所有顶点进行整体偏移;/ 1000是偏移值的缩放倍数,此值越小偏移程度越高。

注意:用这个方法做出来的透视滑动列表,主要的问题是一些交互控件的偏移问题,因为视觉效果偏移了,但是实际上可交互控件的位置没有变,所以其点触范围是没有透视效果时的范围,这就会导致偏移的时候其点触范围不一样,所以需要第二种方法。

第二种方法是使用纯C#来实现,其核心原理是,通过遍历所有子节点的Image和Text节点,同样使用第一种方法的思路修改其VertexHelper中顶点的偏移值,再将修改完的顶点设置回VertexHelper中,然后重新生成一个Mesh,并将Mesh设置为canvasRenderer的Mesh。为了得到正确的点触范围,还需要在节点中添加MeshCollider组件,通过代码设置MeshCollider组件的Mesh属性,并将Image或Text节点的Raycast Target属性取消勾选,这样就能保证最正确的点触范围了。
然后,因为滑动列表是可以滑动的,所以还需要滑动的时候一直通过上述方法动态修改节点,这里使用滑动列表自带的OnValueChange函数就行

注意:使用过多的MeshCollider对性能必定有消耗,不过Image和Text生成的Mesh都是比较简单的,具体的性能消耗还是需要进行测试才能得出结果

3、自定义实现轨迹滑动

核心原理已经在上面说了,这里直接上代码:


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

public class PerspectiveScrollRect : MonoBehaviour
{
    /// <summary>
    /// 中心点,中心点可以设置为不是原点
    /// </summary>
    public Vector3 uiCenterPoint = Vector3.zero;

    /// <summary>
    /// 图片的回拉像素,每距离中心点100个像素往回拉的距离
    /// </summary>
    [Range(0,100)]
    public float perspective = 0;

    public ScrollRect scrollRect;

    /// <summary>
    /// 滑动列表节点
    /// </summary>
    private RectTransfORM scrollRectRectTransform;
    private List<RectTransform> childRectTransformList = new List<RectTransform>();
    private RectTransform rectTransform;

    private void Start()
    {
        scrollRectRectTransform = scrollRect.GetComponent<RectTransform>();
        rectTransform = GetComponent<RectTransform>();
        for(int i = 0;i < transform.childCount;i++)
        {
            if(transform.GetChild(i).gameObject.activeInHierarchy)
            {
                childRectTransformList.Add(transform.GetChild(i).GetComponent<RectTransform>());
            }
        }
        scrollRect.onValueChanged.AddListener(UpdataChilds);
        UpdataChilds(Vector2.zero);
    }

    void UpdataChilds(Vector2 vector2)
    {
        ModifyMesh(new VertexHelper());
    }

    public void ModifyMesh(VertexHelper vh)
    {
        if (!gameObject.activeInHierarchy || childRectTransformList.Count <= 0)
        {
            return;
        }

        foreach(var item in childRectTransformList)
        {
            float offset_left;
            float offset_right;
            Vector3 distanceVector = new Vector3(item.localPosition.x - scrollRectRectTransform.sizeDelta.x / 2 + rectTransform.anchoredPosition.x, item.localPosition.y, 0) - uiCenterPoint;
            //distanceVector.x小于0则证明当前节点在中心点右边,设置的透视左右值需要反过来
            if (distanceVector.x < 0)
            {
                offset_left = -perspective * distanceVector.x / 100f;
                offset_right = -perspective * distanceVector.x / 100f;
            }
            else
            {
                offset_left = -perspective * distanceVector.x / 100f;
                offset_right = -perspective * distanceVector.x / 100f;
            }
            Image[] images = item.GetComponentsInChildren<Image>();
            Text[] texts = item.GetComponentsInChildren<Text>();
            ModifyImagesInItem(offset_left, offset_right, images, item.sizeDelta.y);
            ModifyTextsInItem(offset_left, offset_right, texts, item.sizeDelta.y);
        }

    }

    public void ModifyImagesInItem(float offset_left, float offset_right, Image[] images, float itemHeight)
    {
        VertexHelper vh = new VertexHelper();
        for (int i = 0; i < images.Length; i++)
        {
            Graphic graphic = images[i];
            vh.Clear();
            graphic.OnPopulateMesh_Public(vh);

            var vertexs = new List<UIVertex>();
            vh.GetUIVertexStream(vertexs);

            UIVertex vt;
            float ratio0;
            float ratio1;
            float ratio2;
            float ratio3;
            float graphicPosY = Mathf.Abs(graphic.rectTransform.localPosition.y);

            vt = vertexs[0];
            ratio0 = (Mathf.Abs(vt.position.y) + graphicPosY) / itemHeight;
            vt.position += new Vector3(offset_left * ratio0, 0, 0);
            vh.SetUIVertex(vt, 0);

            vt = vertexs[1];
            ratio1 = (Mathf.Abs(vt.position.y) + graphicPosY) / itemHeight;
            vt.position += new Vector3(offset_left * ratio1, 0, 0);
            vh.SetUIVertex(vt, 1);

            vt = vertexs[2];
            ratio2 = (Mathf.Abs(vt.position.y) + graphicPosY) / itemHeight;
            vt.position += new Vector3(offset_right * ratio2, 0, 0);
            vh.SetUIVertex(vt, 2);

            vt = vertexs[4];
            ratio3 = (Mathf.Abs(vt.position.y) + graphicPosY) / itemHeight;
            vt.position += new Vector3(offset_right * ratio3, 0, 0);
            vh.SetUIVertex(vt, 3);

            Mesh mesh = new Mesh();
            vh.FillMesh(mesh);
            graphic.canvasRenderer.SetMesh(mesh);
            MeshCollider meshCollider = graphic.GetComponent<MeshCollider>();
            if(meshCollider != null)
            {
                meshCollider.sharedMesh = mesh;
            }
        }
    }

    public void ModifyTextsInItem(float offset_left, float offset_right, Text[] texts, float itemHeight)
    {
        VertexHelper vh = new VertexHelper();
        for (int i = 0; i < texts.Length; i++)
        {
            Graphic graphic = texts[i];
            vh.Clear();
            graphic.OnPopulateMesh_Public(vh);

            var vertexs = new List<UIVertex>();
            vh.GetUIVertexStream(vertexs);

            UIVertex vt;
            float ratio;
            float graphicPosY = Mathf.Abs(graphic.rectTransform.localPosition.y);

            int vert_index = 0;

            for (int j = 0; j < vertexs.Count; j++)
            {
                //剔除不必要的顶点
                if((j - 3) % 6 == 0 || (j - 5) % 6 == 0)
                {
                    continue;
                }

                if((j - 0) % 6 == 0 || (j - 1) % 6 == 0)
                {
                    vt = vertexs[j];
                    ratio = (Mathf.Abs(vt.position.y) + graphicPosY) / itemHeight;
                    vt.position += new Vector3(offset_left * ratio, 0, 0);
                    vh.SetUIVertex(vt, vert_index);
                    vert_index++;
                }

                if((j - 2) % 6 == 0 || (j - 4) % 6 == 0)
                {
                    vt = vertexs[j];
                    ratio = (Mathf.Abs(vt.position.y) + graphicPosY) / itemHeight;
                    vt.position += new Vector3(offset_right * ratio, 0, 0);
                    vh.SetUIVertex(vt, vert_index);
                    vert_index++;
                }
            }

            Mesh mesh = new Mesh();
            vh.FillMesh(mesh);
            graphic.canvasRenderer.SetMesh(mesh);
            MeshCollider meshCollider = graphic.GetComponent<MeshCollider>();
            if (meshCollider != null)
            {
                meshCollider.sharedMesh = mesh;
            }
        }
    }
}

因为需要获取到Image组件或Text组件的顶点辅助类VertexHelper,所以需要通过Graphic类的OnPopulateMesh函数来获取VertexHelper类,但是OnPopulateMesh函数是受保护的函数,因为需要在Graphic类中添加一个公用的函数OnPopulateMesh_Public:


public void OnPopulateMesh_Public(VertexHelper toFill)
{
    OnPopulateMesh(toFill);
}

protected virtual void OnPopulateMesh(VertexHelper vh)
{
    var r = GetPixelAdjustedRect();
    var v = new Vector4(r.x, r.y, r.x + r.width, r.y + r.height);

    Color32 color32 = color;
    vh.Clear();
    vh.AddVert(new Vector3(v.x, v.y), color32, new Vector2(0f, 0f));
    vh.AddVert(new Vector3(v.x, v.w), color32, new Vector2(0f, 1f));
    vh.AddVert(new Vector3(v.z, v.w), color32, new Vector2(1f, 1f));
    vh.AddVert(new Vector3(v.z, v.y), color32, new Vector2(1f, 0f));

    vh.AddTriangle(0, 1, 2);
    vh.AddTriangle(2, 3, 0);
}

4、问题

一、首先就是性能方面的消耗,因为滑动时是会一直有计算顶点的消耗的
二、还有就是初始化的问题,在Start函数中已经调用过一次修改顶点的函数了,但是在Unity编辑器模式下的实际效果并没有显示出来,需要手动滑一下才会显示出正确的效果。即使在Start函数中调用两次也是会出现这个问题

5、最终效果

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: Unity实现透视滑动列表

本文链接: https://lsjlt.com/news/131348.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Unity实现透视滑动列表
    本文实例为大家分享了Unity实现透视滑动列表的具体代码,供大家参考,具体内容如下 1、目的 有时候,为了实现更好的美术效果,需要实现一些特殊的滑动列表,例如轨迹滑动,也有透视滑动。...
    99+
    2024-04-02
  • Unity怎么实现透视滑动列表
    本篇内容主要讲解“Unity怎么实现透视滑动列表”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Unity怎么实现透视滑动列表”吧!本文实例为大家分享了Unity实现透视滑动列表的具体代码,供大家...
    99+
    2023-06-20
  • Android仿微信列表滑动删除 如何实现滑动列表SwipeListView
    接上一篇,本篇主要讲如何实现滑动列表SwipeListView。 上篇完成了滑动控件SwipeItemView,这个控件是一个自定义的ViewGroup,作为列表的一个ite...
    99+
    2022-06-06
    列表 Android
  • Unity实现颜色渐变滑动条
    本文实例为大家分享了Unity实现颜色渐变滑动条的具体代码,供大家参考,具体内容如下 效果展示 代码 直接挂在UGUI Slider上即可 using UnityEngine;...
    99+
    2024-04-02
  • Unity ScrollView实现无限滑动效果
    本文实例为大家分享了Unity ScrollView实现无限滑动效果的具体代码,供大家参考,具体内容如下 一、效果演示 二、前言 当邮件中有1000封邮件,商店列表中有1000个物...
    99+
    2024-04-02
  • Unity ScrollRect实现轨迹滑动效果
    本文实例为大家分享了Unity ScrollRect实现轨迹滑动效果的具体代码,供大家参考,具体内容如下 以下内容是根据Unity 2020.1.01f版本进行编写的 1、目的 工作...
    99+
    2024-04-02
  • js如何实现滑动穿透
    这篇文章将为大家详细讲解有关js如何实现滑动穿透,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。场景当页面出现浮层的时候,滑动浮层的内容,正常情况下预期应该是浮层下边的内容...
    99+
    2024-04-02
  • Unity实现滑动更换界面效果
    在做2048这个游戏时,因为菜单页面还能查看游戏规则,而这些规则又不在同一个页上,所以需要滑动页面实现页面切换,但是仅仅使用unity提供的组件做出的效果仅有一个切换的意思,交互感很...
    99+
    2024-04-02
  • iOS实现多个垂直滑动条并列视图
    本文实例为大家分享了iOS实现多个垂直滑动条并列视图的具体代码,供大家参考,具体内容如下 上一篇文章我们实现了一个垂直滑动条的类 (VerticalSlider),用来满足垂直滑动的...
    99+
    2024-04-02
  • Python+Pandas实现数据透视表
    目录导入示例数据参数说明常用操作大家好,我是丁小杰。 对于数据透视表,相信对于 Excel 比较熟悉的小伙伴都知道如何使用它,并了解它的强大之处,而在pandas中要实现数据透视就要...
    99+
    2024-04-02
  • Unity ScrollView如何实现无限滑动效果
    小编给大家分享一下Unity ScrollView如何实现无限滑动效果,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、效果演示二、前言当邮件中有1000封邮件,...
    99+
    2023-06-20
  • Python如何实现数据透视表
    这篇文章主要为大家展示了“Python如何实现数据透视表”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Python如何实现数据透视表”这篇文章吧。用Python里的Pandas可以实现,虽然感觉...
    99+
    2023-06-25
  • Python实现数据透视表详解
    目录1.groupby + agg2. crosstab3.groupby + pivotpivot_table总结用Python里的Pandas可以实现,虽然感觉Excel更方便 ...
    99+
    2024-04-02
  • MySQL/MariaDB怎么实现数据透视表
    这篇文章将为大家详细讲解有关MySQL/MariaDB怎么实现数据透视表,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。使用 CASE 表达式和分组聚合数据透视表的本质就是按照行和列的不同组合进行数据分组,...
    99+
    2023-06-14
  • Oracle中如何实现数据透视表
    这篇文章主要介绍Oracle中如何实现数据透视表,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!使用 CASE 表达式实现数据透视表数据透视表的本质就是按照行和列的不同组合进行数据分组,然后对结果进行汇总;因此,它和数...
    99+
    2023-06-14
  • Python中怎么实现一个透视表
    本篇文章为大家展示了Python中怎么实现一个透视表,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。1. 数据为帮助大家更好地理解,在讲解如何使用pivot_table( )实现透视表前,我们先导入示...
    99+
    2023-06-16
  • 小程序使用scroll-view实现一个滑动列表功能
    目录滑动区域下拉刷新触底加载总结 滑动列表是每个应用必不可少的部分,而实现也是一件复杂的事情,根据上面的动图实现一个滑动列表,需要考虑到如下几点。 列表的滑动区域列表的下拉刷新列表的...
    99+
    2022-11-13
    scroll-view横向滚动 小程序scroll-view scroll-view 滑动列表
  • Unity 实现鼠标滑过UI时触发动画的操作
    在有些需求中会遇到,当鼠标滑过某个UI物体上方时,为了提醒用户该物体是可以交互时,我们需要添加一个动效和提示音。这样可以提高产品的体验感。 解决方案 1、给需要有动画的物体制作相应的...
    99+
    2024-04-02
  • js实现移动端简易滑动表格
    本文实例为大家分享了js实现移动端简易滑动表格的具体代码,供大家参考,具体内容如下 上js文件代码 <template>   <view>     <s...
    99+
    2024-04-02
  • 怎么使用Python+Pandas实现数据透视表
    这篇文章主要介绍了怎么使用Python+Pandas实现数据透视表的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么使用Python+Pandas实现数据透视表文章都会有所收获,下面我们一起来看看吧。导入示例数...
    99+
    2023-07-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作