最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Unity實(shí)現(xiàn)透視滑動(dòng)列表

 更新時(shí)間:2021年07月28日 16:16:35   作者:咸魚永不翻身  
這篇文章主要為大家詳細(xì)介紹了Unity實(shí)現(xiàn)透視滑動(dòng)列表,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文實(shí)例為大家分享了Unity實(shí)現(xiàn)透視滑動(dòng)列表的具體代碼,供大家參考,具體內(nèi)容如下

1、目的

有時(shí)候,為了實(shí)現(xiàn)更好的美術(shù)效果,需要實(shí)現(xiàn)一些特殊的滑動(dòng)列表,例如軌跡滑動(dòng),也有透視滑動(dòng)。
注意:本文里所展示的效果是未經(jīng)測(cè)試的試驗(yàn)版,如果用于實(shí)際項(xiàng)目中,應(yīng)該還需要優(yōu)化代碼和測(cè)試性能

2、思考

透視滑動(dòng)列表可以有兩種方式來實(shí)現(xiàn):

第一種方法是,通過shader實(shí)現(xiàn),其核心原理是,定義一個(gè)中心點(diǎn)坐標(biāo)(CenterX,CenterY),再定義一個(gè)透視系數(shù)_ OffsetPerspective,在vert函數(shù)中,對(duì)于每個(gè)頂點(diǎn),計(jì)算其偏移值,距離自己定義的中心點(diǎn)越遠(yuǎn)的頂點(diǎn),其偏移值越大,簡單概括就是距離中心點(diǎn)越遠(yuǎn)的頂點(diǎn),就越把往中心點(diǎn)拉回去。實(shí)際算法就是:

OUT.worldPosition.x += (_CenterY + v.vertex.y - _OffsetX) / 1000 * (v.vertex.x - _CenterX) * _OffsetPerspective
這是我所使用的計(jì)算公式,其中,_OffsetX是自定義的偏移值,用于對(duì)所有頂點(diǎn)進(jìn)行整體偏移;/ 1000是偏移值的縮放倍數(shù),此值越小偏移程度越高。

注意:用這個(gè)方法做出來的透視滑動(dòng)列表,主要的問題是一些交互控件的偏移問題,因?yàn)橐曈X效果偏移了,但是實(shí)際上可交互控件的位置沒有變,所以其點(diǎn)觸范圍是沒有透視效果時(shí)的范圍,這就會(huì)導(dǎo)致偏移的時(shí)候其點(diǎn)觸范圍不一樣,所以需要第二種方法。

第二種方法是使用純C#來實(shí)現(xiàn),其核心原理是,通過遍歷所有子節(jié)點(diǎn)的Image和Text節(jié)點(diǎn),同樣使用第一種方法的思路修改其VertexHelper中頂點(diǎn)的偏移值,再將修改完的頂點(diǎn)設(shè)置回VertexHelper中,然后重新生成一個(gè)Mesh,并將Mesh設(shè)置為CanvasRenderer的Mesh。為了得到正確的點(diǎn)觸范圍,還需要在節(jié)點(diǎn)中添加MeshCollider組件,通過代碼設(shè)置MeshCollider組件的Mesh屬性,并將Image或Text節(jié)點(diǎn)的Raycast Target屬性取消勾選,這樣就能保證最正確的點(diǎn)觸范圍了。
然后,因?yàn)榛瑒?dòng)列表是可以滑動(dòng)的,所以還需要滑動(dòng)的時(shí)候一直通過上述方法動(dòng)態(tài)修改節(jié)點(diǎn),這里使用滑動(dòng)列表自帶的OnValueChange函數(shù)就行

注意:使用過多的MeshCollider對(duì)性能必定有消耗,不過Image和Text生成的Mesh都是比較簡單的,具體的性能消耗還是需要進(jìn)行測(cè)試才能得出結(jié)果

3、自定義實(shí)現(xiàn)軌跡滑動(dòng)

核心原理已經(jīng)在上面說了,這里直接上代碼:

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

public class PerspectiveScrollRect : MonoBehaviour
{
    /// <summary>
    /// 中心點(diǎn),中心點(diǎn)可以設(shè)置為不是原點(diǎn)
    /// </summary>
    public Vector3 uiCenterPoint = Vector3.zero;

    /// <summary>
    /// 圖片的回拉像素,每距離中心點(diǎn)100個(gè)像素往回拉的距離
    /// </summary>
    [Range(0,100)]
    public float perspective = 0;

    public ScrollRect scrollRect;

    /// <summary>
    /// 滑動(dòng)列表節(jié)點(diǎn)
    /// </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則證明當(dāng)前節(jié)點(diǎn)在中心點(diǎn)右邊,設(shè)置的透視左右值需要反過來
            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++)
            {
                //剔除不必要的頂點(diǎn)
                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;
            }
        }
    }
}

因?yàn)樾枰@取到Image組件或Text組件的頂點(diǎn)輔助類VertexHelper,所以需要通過Graphic類的OnPopulateMesh函數(shù)來獲取VertexHelper類,但是OnPopulateMesh函數(shù)是受保護(hù)的函數(shù),因?yàn)樾枰贕raphic類中添加一個(gè)公用的函數(shù)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、問題

一、首先就是性能方面的消耗,因?yàn)榛瑒?dòng)時(shí)是會(huì)一直有計(jì)算頂點(diǎn)的消耗的
二、還有就是初始化的問題,在Start函數(shù)中已經(jīng)調(diào)用過一次修改頂點(diǎn)的函數(shù)了,但是在Unity編輯器模式下的實(shí)際效果并沒有顯示出來,需要手動(dòng)滑一下才會(huì)顯示出正確的效果。即使在Start函數(shù)中調(diào)用兩次也是會(huì)出現(xiàn)這個(gè)問題

5、最終效果

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • C#/VB.NET中從?PDF?文檔中提取所有表格

    C#/VB.NET中從?PDF?文檔中提取所有表格

    這篇文章主要介紹了C#/VB.NET中從PDF文檔中提取所有表格,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08
  • C#實(shí)現(xiàn)HTML和UBB互相轉(zhuǎn)換的方法

    C#實(shí)現(xiàn)HTML和UBB互相轉(zhuǎn)換的方法

    這篇文章主要介紹了C#實(shí)現(xiàn)HTML和UBB互相轉(zhuǎn)換的方法,通過兩個(gè)自定義函數(shù)DoHtmlToUB與ubbtohtml來實(shí)現(xiàn)HTML代碼與ubb代碼間的相互轉(zhuǎn)換,是非常實(shí)用的技巧,需要的朋友可以參考下
    2014-11-11
  • C#學(xué)習(xí)筆記整理_深入剖析構(gòu)造函數(shù)、析構(gòu)函數(shù)

    C#學(xué)習(xí)筆記整理_深入剖析構(gòu)造函數(shù)、析構(gòu)函數(shù)

    下面小編就為大家?guī)硪黄狢#學(xué)習(xí)筆記整理_深入剖析構(gòu)造函數(shù)、析構(gòu)函數(shù)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-09-09
  • C#編寫發(fā)送郵件組件

    C#編寫發(fā)送郵件組件

    本文給大家分享的是使用C#編寫的發(fā)送郵件的組件,非常的簡單實(shí)用,有需要的小伙伴可以參考下。
    2015-06-06
  • Unity Shader片段著色器使用基礎(chǔ)詳解

    Unity Shader片段著色器使用基礎(chǔ)詳解

    頂點(diǎn)-片段著色器是Unity Shader中最基礎(chǔ)的著色器類型,用于控制3D模型的渲染效果。通過頂點(diǎn)著色器計(jì)算模型的頂點(diǎn)位置和法線方向,再通過片段著色器計(jì)算模型表面的顏色、光照、陰影等效果
    2023-05-05
  • C# TabControl手動(dòng)觸發(fā)DrawItem的實(shí)現(xiàn)

    C# TabControl手動(dòng)觸發(fā)DrawItem的實(shí)現(xiàn)

    本文主要介紹了C# TabControl手動(dòng)觸發(fā)DrawItem的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • C#實(shí)現(xiàn)的簡單整數(shù)四則運(yùn)算計(jì)算器功能示例

    C#實(shí)現(xiàn)的簡單整數(shù)四則運(yùn)算計(jì)算器功能示例

    這篇文章主要介紹了C#實(shí)現(xiàn)的簡單整數(shù)四則運(yùn)算計(jì)算器功能,涉及C#界面布局、事件響應(yīng)及數(shù)值運(yùn)算等相關(guān)操作技巧,需要的朋友可以參考下
    2017-09-09
  • C#中try...catch的使用與常見面試題分享

    C#中try...catch的使用與常見面試題分享

    這篇文章首先給大家介紹了關(guān)于C#中try...catch的語法,而后又給大家分享了關(guān)于C#中try...catch最常見的面試題,具有一定的參考借鑒價(jià)值,需要的朋友們下面來一起看看吧。
    2017-02-02
  • C#實(shí)現(xiàn)treeview綁定的方法

    C#實(shí)現(xiàn)treeview綁定的方法

    這篇文章主要介紹了C#實(shí)現(xiàn)treeview綁定的方法,包括datatable的獲取與節(jié)點(diǎn)的操作,具有一定的參考價(jià)值,需要的朋友可以參考下
    2014-12-12
  • 詳細(xì)介紹C# 泛型

    詳細(xì)介紹C# 泛型

    這篇文章主要介紹了C# 泛型的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)C#,感興趣的朋友可以了解下
    2020-08-08

最新評(píng)論

股票| 绩溪县| 泾阳县| 海兴县| 简阳市| 全南县| 邹平县| 铜山县| 万盛区| 永昌县| 旅游| 岳普湖县| 康平县| 水城县| 峨山| 林西县| 宁远县| 合江县| 玛曲县| 会宁县| 临邑县| 商都县| 邯郸市| 马边| 蒲江县| 象州县| 金山区| 阜新| 理塘县| 德兴市| 甘南县| 天等县| 浮山县| 宁德市| 日喀则市| 珠海市| 称多县| 德化县| 上林县| 曲松县| 岢岚县|