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

Unity ScrollRect實現(xiàn)軌跡滑動效果

 更新時間:2021年09月12日 16:43:34   作者:咸魚永不翻身  
這篇文章主要為大家詳細(xì)介紹了Unity ScrollRect實現(xiàn)軌跡滑動效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了Unity ScrollRect實現(xiàn)軌跡滑動效果的具體代碼,供大家參考,具體內(nèi)容如下

以下內(nèi)容是根據(jù)Unity 2020.1.01f版本進(jìn)行編寫的

1、目的

工作中遇到有需要實現(xiàn)軌跡滑動的滑動列表,通常的做法是計算貝塞爾曲線得出軌跡,但是我覺得計算貝塞爾曲線太麻煩了,或許有沒有更簡單的方法。

2、思考

軌跡滑動可以分兩種情況:

第一種是軌跡滑動是比較簡單的橫向(或縱向)滑動,其中軌跡不會蜿蜒盤旋,也不涉及列表格子之間的重疊關(guān)系,這時可以分區(qū)間來對Y軸(或X軸)進(jìn)行設(shè)置以達(dá)到格子沿著軌跡滑動的效果
例如,軌跡是這樣的波浪型的,其中,軌跡點的數(shù)量可以無限增加,點越多軌跡可以設(shè)置得越平滑,但是消耗的性能也越多:

像這樣,類似波浪型的軌跡,可以用一個Vector列表記錄下每個點的位置和順序,然后根據(jù)每個格子所在的位置,先由小到大循環(huán)判斷在哪個區(qū)間,例如格子3在pos_5和pos_6中間,所以第三個格子的區(qū)間就是5,然后通過pos_5和pos_6兩個點相減,得到一個從pos_5指向pos_6的向量vector,通過vector3.distance函數(shù)得到pos_5和pos_6兩個點的橫向距離distanceX1,然后再次通過vector3.distance函數(shù)得到pos_5與格子3得橫向距離distanceX2,那么,格子3的位置 = pos_5的位置 + distanceX2 / distanceX1 * vector,得到位置后再把位置設(shè)置回去就可以了 

第二種就是更為復(fù)雜的軌跡滑動,例如蜿蜒盤旋式的軌跡,其中還包括有層級關(guān)系

例如,軌跡是蜿蜒盤旋的,同樣是軌跡點越多,曲線越平滑,也越消耗性能:

像這樣,蜿蜒盤旋的軌跡,就不能使用第一種方法了,因為有些位置,一個X值對應(yīng)下來有多個Y值,無法區(qū)分當(dāng)前需要的是哪個Y值,所以,需要使用另一種方法

我們可以通過獲取所有的軌跡點,計算出每兩個相鄰軌跡點之間的距離,通過距離確定格子應(yīng)該在哪個區(qū)間內(nèi)

例如,格子3的位置是95,假設(shè)pos_1和pos_2的距離為50,pos_2和pos_3的距離為也是50,那么pos_1到pos_3的總距離就是100,所以格子3應(yīng)該在區(qū)間pos_2和pos_3中間。接下來計算實際位置,因為此時格子的X軸和Y軸都會變化,同樣無法使用第一種方法來計算格子的位置,需要通過格子的位置減去前面區(qū)間距離的和,在例子中,就是格子3的位置減去pos_1到pos_2的距離,即95 – 50 = 45,再通過剩余的距離除以當(dāng)前區(qū)間的距離得出比例ratio,然后就是通過當(dāng)前的兩個區(qū)間點相減得到pos_2指向pos_3的向量vector,那么格子3的位置就是,pos_2的位置 + ratio * vector

最后,還有層級的問題,也就是哪個格子遮擋哪個格子,一般是后面的格子遮擋前面的格子,如果需要前面的遮擋后面的格子,只需要動態(tài)修改層級就行,unity提供了這個函數(shù):Transform.SetAsFirstSibling()

在實際使用中,我發(fā)現(xiàn)使用這種方法后,content的長度有時候會過長,有時候會過短,所以需要確定好格子的數(shù)量,設(shè)置好content的正確長度

注意:以上都是最基礎(chǔ)的思想,因為滑動時改變的是content節(jié)點,格子的位置實際上是不變的,或者是由代碼設(shè)置的,所以實際代碼中還需要考慮scrollrect的寬高以及content節(jié)點的滑動值(即posX值,滑動時此值會變化)

3、自定義實現(xiàn)軌跡滑動

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

[RequireComponent(typeof(ScrollRect))]
public class CurveSliding : MonoBehaviour
{
    public Transform posListRoot;
    public float contentwidth;              //必須自己設(shè)置的content實際長度
    public bool isChangeHierarchy = false;

    private ScrollRect scrollRect;
    private RectTransform content;
    private List<Transform> posTransformList = new List<Transform>();
    private List<RectTransform> item_transformList = new List<RectTransform>();
    private List<float> posX_List = new List<float>();
    private List<float> distanceList = new List<float>();
    private float scrollRectWidth;
    private float scrollRectHeight;
    private float posTotalDistance;
    private float spacing = 0;

    private void Start()
    {
        scrollRect = GetComponent<ScrollRect>();
        content = scrollRect.content.transform as RectTransform;
        HorizontalLayoutGroup contentLayoutGroup = content.GetComponentsInChildren<HorizontalLayoutGroup>(true)[0];
        if(contentLayoutGroup != null && contentLayoutGroup.name == content.name)
        {
            spacing = contentLayoutGroup.spacing;
        }
        scrollRectWidth = scrollRect.GetComponent<RectTransform>().sizeDelta.x;
        scrollRectHeight = scrollRect.GetComponent<RectTransform>().sizeDelta.y;
        for (int i = 0; i < content.childCount; i++)
        {
            RectTransform item_transform = content.GetChild(i) as RectTransform;
            if (item_transform.gameObject.activeInHierarchy)
            {
                item_transformList.Add(item_transform);
                posX_List.Add(item_transform.localPosition.x);
            }
            else
            {
                continue;
            }
        }
        float totalDistance = 0;
        for(int i = 0;i < posListRoot.childCount;i++)
        {
            Transform posTransform = posListRoot.GetChild(i);
            if (i > 0)
            {
                Transform previousPosTransform = posListRoot.GetChild(i - 1);
                totalDistance += Vector3.Distance(posTransform.localPosition, previousPosTransform.localPosition);
            }
            posTransformList.Add(posTransform);
            distanceList.Add(totalDistance);
        }
        posTotalDistance = distanceList[distanceList.Count - 1];
        content.sizeDelta = new Vector2(contentwidth, content.sizeDelta.y);
        OnValueChange(Vector2.zero);
        scrollRect.onValueChanged.AddListener(OnValueChange);
    }

    public void OnValueChange(Vector2 vector)
    {
        for(int i = 0;i < item_transformList.Count;i++)
        {
            float localPosX = posX_List[i];
            float posX = localPosX + content.anchoredPosition.x;
            //如果當(dāng)前節(jié)點的位置 - content的X軸偏移值 > 滑動列表的寬度,則說明當(dāng)前item在可視范圍外
            if (posX > posTotalDistance + 200 || posX < 0)
            {
                continue;
            }
            int index = -1;
            foreach(var totalDistance in distanceList)
            {
                if(posX < totalDistance)
                {
                    break;
                }
                else
                {
                    index++;
                }
            }
            //如果index+1小于位置列表的數(shù)量,則其在位置區(qū)間內(nèi),否則應(yīng)該在位置區(qū)間外
            if (index + 1 < posListRoot.childCount && index + 1 > 0)
            {
                float ratio = (posX - distanceList[index]) / (distanceList[index + 1] - distanceList[index]);
                Vector3 newPos = posTransformList[index].localPosition - ratio * (posTransformList[index].localPosition - posTransformList[index + 1].localPosition);
                item_transformList[i].localPosition = new Vector3(newPos.x + scrollRectWidth/2 - content.anchoredPosition.x, -scrollRectHeight / 2 + newPos.y, 0);

            }
            else if(index <= -1)
            {
                item_transformList[i].localPosition = new Vector3(item_transformList[i].localPosition.x, -scrollRectHeight / 2 + posListRoot.GetChild(0).localPosition.y, 0);
            }
            else if(index >= posListRoot.childCount - 1)
            {
                if (i < 1)
                {
                    continue;
                }
                RectTransform previousItem_RectTransform = item_transformList[i - 1];
                item_transformList[i].localPosition = new Vector3(previousItem_RectTransform.localPosition.x + spacing + previousItem_RectTransform.sizeDelta.x/2 + item_transformList[i].sizeDelta.x/2, -scrollRectHeight / 2 + posListRoot.GetChild(posListRoot.childCount - 1).localPosition.y, 0);
            }
            if (isChangeHierarchy)
            {
                item_transformList[i].SetAsFirstSibling();
            }
        }
    }
}

4、兩種方法的優(yōu)缺點

1)、 兩種方法都不能使用排序組件,因為排序組件會控死格子的位置,通過代碼也無法修改
2)、 第二種方法比第一種方法更復(fù)雜,同時消耗的性能也更多,但是能實現(xiàn)更復(fù)雜的效果
3)、第二種方法需要設(shè)置conten的長度,即格子的數(shù)量無法動態(tài)變化,是一大缺點

5、最終效果

第一種:

第二種:

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

相關(guān)文章

  • c#訪問this關(guān)鍵字和base關(guān)鍵字示例

    c#訪問this關(guān)鍵字和base關(guān)鍵字示例

    this關(guān)鍵字引用類的當(dāng)前實例。靜態(tài)成員方法中不能使用this關(guān)鍵字,this關(guān)鍵字只能在實例構(gòu)造函數(shù)、實例方法或?qū)嵗L問器中使用。base關(guān)鍵字用于從派生類中訪問基類的成員。下面學(xué)習(xí)一下這二個關(guān)鍵字的使用方法
    2014-01-01
  • C# 使用Free Spire.Presentation 實現(xiàn)對PPT插入、編輯、刪除表格

    C# 使用Free Spire.Presentation 實現(xiàn)對PPT插入、編輯、刪除表格

    小編發(fā)現(xiàn)使用.NET組件——Free Spire.Presentation,在C#中添加該產(chǎn)品DLL文件,可以簡單快速地實現(xiàn)對演示文稿的表格插入、編輯和刪除等操作,具體實現(xiàn)代碼大家參考下本文吧
    2017-09-09
  • c#操作sql server2008 的界面實例代碼

    c#操作sql server2008 的界面實例代碼

    這篇文章主要介紹了c#操作sql server2008 的界面實例代碼,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-03-03
  • C# 手動/自動保存圖片的實例代碼

    C# 手動/自動保存圖片的實例代碼

    C# 手動/自動保存圖片的實例代碼,需要的朋友可以參考一下
    2013-03-03
  • 關(guān)于C# TabPage如何隱藏的問題

    關(guān)于C# TabPage如何隱藏的問題

    TabPage沒有Visible屬性,所以只能通過設(shè)置將其與父控件(tabcontrol)的關(guān)聯(lián)性去除就好了,如下面代碼:
    2013-04-04
  • C#零基礎(chǔ)開發(fā)中最重要的概念總結(jié)

    C#零基礎(chǔ)開發(fā)中最重要的概念總結(jié)

    這篇文章主要為大家詳細(xì)介紹了C#零基礎(chǔ)開發(fā)中最重要的一些概念,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)C#有一定的幫助,需要的可以參考一下
    2023-02-02
  • 詳解C# 線程的掛起與喚醒

    詳解C# 線程的掛起與喚醒

    這篇文章主要介紹了詳解C# 線程的掛起與喚醒,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下
    2021-05-05
  • unity 鼠標(biāo)懸停事件操作

    unity 鼠標(biāo)懸停事件操作

    這篇文章主要介紹了unity 鼠標(biāo)懸停事件操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • WinForm遍歷窗體所有子控件的方法

    WinForm遍歷窗體所有子控件的方法

    這篇文章主要介紹了WinForm遍歷窗體所有子控件的方法,涉及C#遞歸遍歷相關(guān)操作技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2016-07-07
  • 深入分析C# 線程同步

    深入分析C# 線程同步

    這篇文章主要介紹了C# 線程同步的的相關(guān)資料,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06

最新評論

确山县| 淮滨县| 罗平县| 清流县| 得荣县| 泽库县| 潞城市| 虎林市| 靖江市| 龙川县| 武山县| 明光市| 霍林郭勒市| 宣城市| 来凤县| 十堰市| 临沭县| 平潭县| 星座| 文安县| 庄浪县| 雷波县| 上犹县| 阳山县| 嘉兴市| 翼城县| 措美县| 会同县| 海阳市| 深泽县| 大邑县| 永定县| 和田县| 揭阳市| 平山县| 郸城县| 新晃| 宁德市| 昆明市| 兴城市| 溆浦县|