亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Unity怎么實現透視滑動列表

發布時間:2021-07-28 19:12:04 來源:億速云 閱讀:224 作者:chen 欄目:開發技術

本篇內容主要講解“Unity怎么實現透視滑動列表”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Unity怎么實現透視滑動列表”吧!

本文實例為大家分享了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、最終效果

Unity怎么實現透視滑動列表

到此,相信大家對“Unity怎么實現透視滑動列表”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

西峡县| 克拉玛依市| 巧家县| 眉山市| 东台市| 龙胜| 安远县| 家居| 卢湾区| 京山县| 泸定县| 沙田区| 抚宁县| 木里| 寿阳县| 城步| 中宁县| 高邑县| 若羌县| 嵩明县| 彭州市| 安阳市| 阜阳市| 房产| 峨眉山市| 姜堰市| 英德市| 林州市| 靖宇县| 柳河县| 永靖县| 建阳市| 富民县| 昌黎县| 昌图县| 大渡口区| 页游| 买车| 勃利县| 长葛市| 思茅市|