Unity-ScrollView无限循环

Unity-ScrollView无限循环

在Unity引擎中ScrollView组件是一个使用率比较高的组件,该组件能上下或者左右拖动的UI列表,背包、展示多个按钮等情况的时候会用到,在做排行榜类似界面时,item非常多,可能有几百个,一次创建这么多GameObject是非常卡的。为此,使用只创建可视区一共显示的个数,加上后置准备个数。

ItemArray

在这里插入图片描述
我们实现无限循环的核心思想是,当滚动框向左移动时,就判断左边的第一个Item距离显示框左边框的距离,是否大于Item的宽度,如果大于则把第一个Item放到最后的位置,当滚动框向右移动时就判断右边的Item距离右边框的距离情况,这样我们就可以在显示区域一直看到有Item的规则显示

按照上面的逻辑分析重写ScrollRect使其支持item回收模式。如果勾选isRecyItem则在运行时在Awake时自动执行回收模式的初始化,否则,需要手动调用,OnInitItemCompleteAct来注册Item的生成回调,用来执行指定item的目标操作。
注: 重写之后不能支持横向和纵向同时滑动

开袋即食的代码:

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

public class MyScrollView : ScrollRect
{
    [HideInInspector]//是否开启循环Item
    public bool isRecyItem = true;
    [HideInInspector]//是否为横向滑动
    public bool isHorizontal = false;
    [HideInInspector]//Item预制体
    public GameObject prefab;
    [HideInInspector]//Item数量
    public int itemCount=10;
    [HideInInspector]//行
    public int hang=1;
    [HideInInspector]//列
    public int lie=1;
    [HideInInspector]//Item大小
    public Vector2 itemSize;
    [HideInInspector]//item间隔
    public Vector2 itemSpace;
    [HideInInspector]//补充组数
    public int fillCount=1;
    private static MyScrollView instance;
    private RecyclerScrollViewBase recycler;
    private bool startUpdate = false;
    private Action OnUpdateAct;
    protected override void Awake()
    {
        base.Awake();
        instance = this;
        if (isRecyItem&&Application.isPlaying)
        {
            InitRecycler(null);
        }
    }

    /// <summary>
    /// 初始化回收器
    /// </summary>
    public RecyclerScrollViewBase  InitRecycler(Action<ItemMoudle> initItemAct)
    {
        if (recycler!=null)
        {
            recycler.Dispose();
            recycler = null;
        }
        if (isHorizontal)
        {
            recycler=new HorizontalScrollView();
        }
        else
        {
            recycler=new VerticalScrollView();
        }
        recycler.OnInit(initItemAct);
        isRecyItem = true;
        return recycler;
    }
    
    public RecyclerScrollViewBase OnInitItemCompleteAct(Action<ItemMoudle> initItemAct)
    {
        recycler?.OnInitItemCompleteAct(initItemAct);
        return recycler;
    }

    private void Update()
    {
        OnUpdateAct?.Invoke();
    }

    protected override void OnDestroy()
    {
        base.OnDestroy();
        recycler?.Dispose();
    }

    /// <summary>
    /// 回收模式的ScrollView基类
    /// </summary>
    public abstract class RecyclerScrollViewBase
    {
        /// <summary>
        /// Grid上一帧所在的位置,用于校验滑动方向
        /// </summary>
        private Vector2 gridLastPos;
        public enum MoveDir
        {
            Idle,
            UP,
            DOWN,
            LEFT,
            RIGHT
        }
        protected RectTransform grid;
        protected RectTransform mask;
        protected float maskWidth;
        protected float maskHeight;
        protected float gridWidth;
        protected float gridHeight;
        protected int viewCount;
        protected float spaceX;
        protected float spaceY;
        protected float itemWidth;
        protected float itemHeight;
        protected int fillCount;
        protected int itemCount;
        protected GameObject prefab;
        protected List<ItemMoudle> itemList;
        protected int itemListCount;
        /// <summary>
        /// 滑动方向
        /// </summary>
        protected MoveDir moveDir;
        protected Action<ItemMoudle> OnInitItemAct;
        /// <summary>
        /// 横向滑动时使用  表示一列有几个元素
        /// </summary>
        protected int hang;
        /// <summary>
        /// 纵向滑动时使用表示一行有几个元素
        /// </summary>
        protected int lie;
        

        public RecyclerScrollViewBase()
        {
            grid = instance.content;
            mask = instance.viewport;
            maskWidth = mask.rect.width;
            maskHeight = mask.rect.height;
            spaceX = instance.itemSpace.x;
            spaceY = instance.itemSpace.y;
            itemWidth = instance.itemSize.x;
            itemHeight = instance.itemSize.y;
            itemCount = instance.itemCount;
            prefab = instance.prefab;
            hang = instance.hang;
            lie = instance.lie;
            fillCount = instance.fillCount;
            
            InitGridSize();
            viewCount=InitViewCount();
            SetAnchors(grid);
            grid.sizeDelta = InitGridSize();
            instance.StopMovement();
            grid.anchoredPosition=Vector2.zero;
            gridWidth = grid.sizeDelta.x;
            gridHeight = grid.sizeDelta.y;
        }

        /// <summary>
        /// 初始化
        /// </summary>
        public void OnInit(Action<ItemMoudle> initItemAct)
        {
            OnInitItemAct = initItemAct;
            itemList=new List<ItemMoudle>();
            ClearGrid();
            for (int i = 0; i < viewCount+fillCount; i++)
            {
                RectTransform trans=Instantiate(prefab, grid).GetComponent<RectTransform>();
                trans.sizeDelta=new Vector2(itemWidth,itemHeight);
                SetAnchors(trans);
                ItemMoudle itemMoudle= new ItemMoudle(i,trans);
                OnInitItemAct?.Invoke(itemMoudle);
                itemList.Add(itemMoudle);
            }
            itemListCount = itemList.Count;
            instance.OnUpdateAct = OnUpdate;
        }

        public void OnInitItemCompleteAct(Action<ItemMoudle> initItemAct)
        {
            OnInitItemAct = initItemAct;
            if (itemList==null||itemList.Count==0)
            {
                return;
            }
            for (int i = 0; i < itemList.Count; i++)
            {
                ItemMoudle item = itemList[i];
                OnInitItemAct?.Invoke(item);
            }
        }

        /// <summary>
        /// Update
        /// </summary>
        private void OnUpdate()
        {
            Vector2 gridCurPos = grid.anchoredPosition;
            Vector2 dir = gridCurPos - gridLastPos;
            if (dir.x>0)
            {
                moveDir = MoveDir.RIGHT;
            }else if (dir.x<0)
            {
                moveDir = MoveDir.LEFT;
            }else if (dir.y>0)
            {
                moveDir = MoveDir.UP;
            }else if (dir.y<0)
            {
                moveDir = MoveDir.DOWN;
            }else
            {
                moveDir = MoveDir.Idle;
            }
            gridLastPos = gridCurPos;
            if (moveDir!=MoveDir.Idle)
            {
                OnMoving(moveDir);
            }
        }

        /// <summary>
        /// 设置锚点
        /// </summary>
        /// <param name="rect"></param>
        protected abstract void SetAnchors(RectTransform rect);

        /// <summary>
        /// ScrollView正在滑动
        /// </summary>
        /// <param name="moveDir"></param>
        protected abstract void OnMoving(MoveDir moveDir);

        /// <summary>
        /// 初始化Grid大小
        /// </summary>
        /// <returns></returns>
        protected abstract Vector2 InitGridSize();

        /// <summary>
        /// 初始化可视区域Item的数量
        /// </summary>
        /// <returns></returns>
        protected abstract int InitViewCount();

        /// <summary>
        /// 清空Grid下所有的子物体
        /// </summary>
        protected void ClearGrid()
        {
            if (grid==null||grid.childCount==0)
            {
                return;
            }

            for (int i = 0; i <grid.childCount; i++)
            {
                Destroy(grid.GetChild(i).gameObject);
            }
        }

        public void Dispose()
        {
            instance.OnUpdateAct = null;
            OnInitItemAct = null;
            grid = null;
            mask = null;
            prefab = null;
            if (itemList!=null&&itemList.Count>0)
            {
                for (int i = itemList.Count-1; i >=0; i--)
                {
                    itemList[i].Dispose();
                    itemList[i] = null;
                }
                itemList.Clear();
            }
        }

    }

    /// <summary>
    /// 横向ScrollView
    /// </summary>
    public class HorizontalScrollView:RecyclerScrollViewBase
    {
        public HorizontalScrollView():base()
        {
            fillCount = fillCount * hang;
        }

        protected override Vector2 InitGridSize()
        {
            float height = grid.sizeDelta.y;
            int grid_lie = itemCount % hang == 0 ? itemCount / hang : itemCount / hang + 1;
            float width = itemWidth*grid_lie+spaceX*(grid_lie-1);
            return new Vector2(width,height);
        }

        protected override void SetAnchors(RectTransform rect)
        {
            rect.anchorMin=new Vector2(0, 0.5f);
            rect.anchorMax=new Vector2(0, 0.5f);
            rect.pivot= new Vector2(0,0.5f);
        }

        protected override void OnMoving(MoveDir moveDir)
        {
            if (moveDir==MoveDir.LEFT)
            {
                if (itemList[itemListCount-1].index==itemCount-1)
                {
                    return;
                }
                MoveToLeft();
            }else if (moveDir==MoveDir.RIGHT)
            {
                if (itemList[0].index==0)
                {
                    return;
                }
                MoveToRight();
            }
        }

        /// <summary>
        /// Item 距离左侧的距离
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        protected float ItemDisLeft(ItemMoudle item)
        {
            float itemX = item.position.x;
            float gridX = -grid.anchoredPosition.x;
            return gridX - itemX - itemWidth;
        }

        /// <summary>
        /// Item 距离右侧的距离
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        protected float ItemDisRight(ItemMoudle item)
        {
            float itemX = item.position.x;
            float gridX = -grid.anchoredPosition.x;
            return itemX-gridX-maskWidth;
        }

        private void MoveToLeft()
        {
            ItemMoudle firstItem =itemList[0];
            float itemDisViewportX = ItemDisLeft(firstItem);
            while (itemDisViewportX>=0)
            {
                ItemMoudle lastItem = itemList[itemListCount-1];
                bool target_isIntactGroup = firstItem.isIntactGroup;
                for (int i = 0; i < hang; i++)//每次移动一排
                {
                    int targetIndex = lastItem.index + 1;
                    if (targetIndex>=itemCount)
                    {
                        return;
                    }
                    firstItem.ChangeIndex(targetIndex);
                    OnInitItemAct?.Invoke(firstItem);
                    itemList.RemoveAt(0);
                    itemList.Insert(itemListCount-1,firstItem);
                    lastItem=itemList[itemListCount-1];
                    firstItem =itemList[0];
                    if (!target_isIntactGroup&&firstItem.isIntactGroup)
                    {
                        break;
                    }
                }
                itemDisViewportX = ItemDisLeft(firstItem);
            }
        }

        private void MoveToRight()
        {
            ItemMoudle lastItem = itemList[itemListCount-1];
            float itemDisViewportX = ItemDisRight(lastItem);
            while (itemDisViewportX>=0)
            {
                bool target_isIntactGroup = lastItem.isIntactGroup;
                for (int i = 0; i < hang; i++)
                {
                    int targetIndex = itemList[0].index - 1;
                    if (targetIndex<0)
                    {
                        return;
                    }
                    lastItem.ChangeIndex(targetIndex);
                    OnInitItemAct?.Invoke(lastItem);
                    itemList.RemoveAt(itemListCount-1);
                    itemList.Insert(0,lastItem);
                    lastItem = itemList[itemListCount-1];
                    if (!target_isIntactGroup&&lastItem.isIntactGroup)
                    {
                        break;
                    }
                }
                itemDisViewportX = ItemDisRight(lastItem);
            }
            
        }

        protected override int InitViewCount()
        {
            return hang*(int)Math.Ceiling((maskWidth + spaceX) / (itemWidth + spaceX));
        }
    }

    /// <summary>
    /// 纵向滑动的ScrollView
    /// </summary>
    public class VerticalScrollView:RecyclerScrollViewBase
    {
        public VerticalScrollView():base()
        {
            fillCount = fillCount * lie;
        }

        protected override Vector2 InitGridSize()
        {
            int grid_hang = itemCount % lie == 0 ? itemCount / lie : itemCount / lie + 1;
            float height = itemHeight*grid_hang+spaceY*(grid_hang-1);
            float width = grid.sizeDelta.x;
            return new Vector2(width,height);
        }
        
        protected override void SetAnchors(RectTransform rect)
        {
            rect.anchorMin=new Vector2(0.5f, 1);
            rect.anchorMax=new Vector2(0.5f, 1);
            rect.pivot= new Vector2(0.5f,1);
        }
        
        protected override int InitViewCount()
        {
            return lie*(int)Math.Ceiling((maskHeight+ spaceY) / (itemHeight + spaceY));
        }
        
        protected override void OnMoving(MoveDir moveDir)
        {
            if (moveDir==MoveDir.UP)
            {
                if (itemList[itemListCount-1].index==itemCount-1)
                {
                    return;
                }
                MoveToUp();
                
            }else if (moveDir==MoveDir.DOWN)
            {
                if (itemList[0].index==0)
                {
                    return;
                }
                MoveToDown();
            }
        }

        /// <summary>
        /// Item 距离上边框的距离
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        protected float ItemDisTop(ItemMoudle item)
        {
            float itemY = -item.position.y;
            return grid.anchoredPosition.y - itemY - itemHeight;
        }

        /// <summary>
        /// item 距离下边框的位置
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        protected float ItemDisBottom(ItemMoudle item)
        {
            float itemY = -item.position.y;
            float contentY = grid.anchoredPosition.y;
            return itemY-contentY-maskHeight;
        }

        /// <summary>
        /// 向上移动
        /// </summary>
        private void MoveToUp()
        {
            ItemMoudle firstItem =itemList[0];
            float itemDisViewportY = ItemDisTop(firstItem);
            while (itemDisViewportY>=0)
            {
                bool target_isIntactGroup = firstItem.isIntactGroup;//当前检查的item是不是属于一个完整组
                ItemMoudle lastItem = itemList[itemListCount-1];
                for (int i = 0; i < lie; i++)
                {
                    int targetIndex = lastItem.index + 1;
                    if (targetIndex>=itemCount)
                    {
                        return;
                    }
                    firstItem.ChangeIndex(targetIndex);
                    OnInitItemAct?.Invoke(firstItem);
                    itemList.RemoveAt(0);
                    itemList.Insert(itemListCount-1,firstItem);
                    lastItem = itemList[itemListCount-1];
                    firstItem =itemList[0];
                    if (!target_isIntactGroup&&firstItem.isIntactGroup)
                    {
                        break;
                    }
                }
                itemDisViewportY = ItemDisTop(firstItem);
            }
            
        }

        /// <summary>
        /// 向下移动
        /// </summary>
        private void MoveToDown()
        {
            ItemMoudle lastItem = itemList[itemListCount-1];
            float itemDisViewportY = ItemDisBottom(lastItem);
            while (itemDisViewportY>=0)
            {
                bool target_isIntactGroup = lastItem.isIntactGroup;
                for (int i = 0; i < lie; i++)
                {
                    int targetIndex = itemList[0].index - 1;
                    if (targetIndex<0)
                    {
                        return;
                    }
                    lastItem.ChangeIndex(targetIndex);
                    OnInitItemAct?.Invoke(lastItem);
                    itemList.RemoveAt(itemListCount-1);
                    itemList.Insert(0,lastItem);
                    lastItem = itemList[itemListCount-1];
                    if (!target_isIntactGroup&&lastItem.isIntactGroup)
                    {
                        break;
                    }
                }
                itemDisViewportY =ItemDisBottom(lastItem);
            }
        }
    }

    /// <summary>
    /// Item模型
    /// </summary>
    public class ItemMoudle
    {
        private float itemWidth;
        private float itemHeight;
        private float spaceX;
        private float spaceY;
        private bool isHorizontal;
        private int hang;
        private int lie;
        private int m_index;
        private RectTransform m_transform;
        private bool m_isIntactGroup;
        /// <summary>
        /// 纵向滑动时每一列的x坐标数组
        /// </summary>
        private static float[] xPosArr;
        /// <summary>
        /// 横向滑动时每一排的y坐标数组
        /// </summary>
        private static float[] yPosArr;
        /// <summary>
        /// 坐标数组是不是已经初始化
        /// </summary>
        private static bool initPosArrEnd = false;

        /// <summary>
        /// 卡牌索引
        /// </summary>
        public int index
        {
            get => m_index;
            private set => m_index = value;
        }
        /// <summary>
        /// 卡牌坐标
        /// </summary>
        public Vector2 position;

        public RectTransform transform
        {
            private set => m_transform = value;
            get => m_transform;
        }
        
        /// <summary>
        /// 是不是一个完整组
        /// </summary>
        public bool isIntactGroup
        {
            get => m_isIntactGroup;
            private set=> m_isIntactGroup= value;
        }

        public ItemMoudle(int _index,RectTransform _rectTransform)
        {
            itemWidth = instance.itemSize.x;
            itemHeight = instance.itemSize.y;
            spaceX = instance.itemSpace.x;
            spaceY = instance.itemSpace.y;
            isHorizontal = instance.isHorizontal;
            hang = instance.hang;
            lie = instance.lie;
            
            if (!initPosArrEnd)
            {
                InitPosArr();
            }
            index = _index;
            position=GetItemLocalPosition();
            if (_rectTransform)
            {
                transform = _rectTransform;
                transform.anchoredPosition = position;
                transform.name = index.ToString();
            }
            isIntactGroup = CheckIntactGroup();
        }

        /// <summary>
        /// 改变item索引
        /// </summary>
        /// <param name="_index">item目标索引</param>
        public void ChangeIndex(int _index)
        {
            index = _index;
            position=GetItemLocalPosition();
            transform.name = index.ToString();
            transform.anchoredPosition = position;
            isIntactGroup = CheckIntactGroup();
        }

        public void Dispose()
        {
            initPosArrEnd = false;
            transform = null;
            xPosArr = null;
            yPosArr = null;
        }


        /// <summary>
        /// 获取当前item的坐标位置
        /// </summary>
        /// <returns></returns>
        private Vector2 GetItemLocalPosition()
        {
            float x, y;
            if (isHorizontal)
            {
                Vector2Int pos = GetGridPos();
                x = (pos.y)*(itemWidth+spaceX);
                y =yPosArr[pos.x];
                return new Vector2(x,y);
            }
            else
            {
                Vector2Int pos = GetGridPos();
                y = -(pos.y)*(itemHeight+spaceY);
                x = xPosArr[pos.x];
                return new Vector2(x,y);
            }
        }

        /// <summary>
        /// 获取当前item的Grid位置(第几行?第几列?)
        /// </summary>
        /// <returns>v2Int x=>列  y=>行</returns>
        private Vector2Int GetGridPos()
        {
            int grid_hang, grid_lie;
            if (isHorizontal)
            {
                grid_hang = (index) / hang;
                grid_lie = (index) % hang;
            }
            else
            {
                grid_hang = (index) / lie;
                grid_lie = (index) % lie;
            }
            return new Vector2Int(grid_lie,grid_hang);
        }

        /// <summary>
        /// 初始化xPosArr和yPosArr
        /// </summary>
        private void InitPosArr()
        {
            initPosArrEnd = true;
            bool isOddNumber;//数组长度是否为奇数
            float startValue;
            float itemFullSpace;
            if (isHorizontal)
            {
                isOddNumber = hang % 2 == 1;
                itemFullSpace = itemHeight + spaceY;
                if (isOddNumber)
                {
                    startValue = (hang / 2)*(itemFullSpace);
                }
                else
                {
                    startValue = (hang / 2-0.5f) * (itemFullSpace);
                }
                yPosArr = new float[hang];
                for (int i = 0; i < hang; i++)
                {
                    yPosArr[i] = startValue - i * itemFullSpace;
                }
            }else
            {
                isOddNumber = lie % 2 == 1;
                itemFullSpace = itemWidth + spaceX;
                if (isOddNumber)
                {
                    startValue = -(lie / 2)*(itemFullSpace);
                }
                else
                {
                    startValue = -(lie / 2-0.5f) * (itemFullSpace);//-itemFullSpace;
                }
                xPosArr=new float[lie];
                for (int i = 0; i < lie; i++)
                {
                    xPosArr[i] = startValue + i * itemFullSpace;
                }
            }
        }

        /// <summary>
        /// 检查是不是一个完整组
        /// </summary>
        bool CheckIntactGroup()
        {
            int itemCount = instance.itemCount;
            if (isHorizontal)
            {
                int v=itemCount % hang;
                if (v==0||index<itemCount-v)
                {
                    return true;
                }
                return false;
            }
            else
            {
                int v=itemCount % lie;
                if (v==0||index<itemCount-v)
                {
                    return true;
                }
                return false;
            }
        }
    }

}

Inspector拓展

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(MyScrollView))]
public class MyScrollViewEditor : Editor
{
    private MyScrollView scrollView;
    private SerializedProperty prefab;

    private void Awake()
    {
        scrollView=target as MyScrollView;
        prefab = this.serializedObject.FindProperty("prefab");
        
    }

    public override void OnInspectorGUI()
    {
        scrollView.isRecyItem = EditorGUILayout.Toggle("回收模式(isRecyItem)", scrollView.isRecyItem);
        if (scrollView.isRecyItem)
        {
            EditorGUILayout.BeginHorizontal();
            scrollView.isHorizontal=EditorGUILayout.Toggle("是否为横向滑动(isHorizontal)", scrollView.isHorizontal);
            scrollView.horizontal = scrollView.isHorizontal;
            scrollView.vertical = !scrollView.horizontal;
            if (scrollView.isHorizontal)
            {
                scrollView.hang = EditorGUILayout.IntField("行数", scrollView.hang);
            }else
            {
                scrollView.lie = EditorGUILayout.IntField("列数", scrollView.lie);
            }
            EditorGUILayout.EndHorizontal();
            scrollView.itemSize = EditorGUILayout.Vector2Field("ItemSize", scrollView.itemSize);
            scrollView.itemSpace = EditorGUILayout.Vector2Field("ItemSpace", scrollView.itemSpace);
            scrollView.itemCount = EditorGUILayout.IntField("元素数量(itemCount)", scrollView.itemCount);
            scrollView.fillCount = EditorGUILayout.IntField("补充组数(fillCount)", scrollView.fillCount);
            EditorGUILayout.PropertyField(serializedObject.FindProperty("prefab"),new GUIContent("预制体"));
            if (GUI.changed)
            {
                serializedObject.ApplyModifiedProperties();
            }
        }
        
        base.OnInspectorGUI();
        
        
    }
}

使用

public MyScrollView myScrollView;
myScrollView.OnInitItemCompleteAct((MyScrollView.ItemMoudle item) =>
        {
            Text t = item.transform.Find("Text").GetComponent<Text>();
            t.text = item.index.ToString();
        });
  • 9
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
怎样才能在Unity中实现Scroll View(滚动视图)的功能呢? 实现Scroll View的方法如下: 1.在Unity中新建一个空白场景。 2.在Hierarchy面板中,右键点击“Create Empty”并选择“UI->Scrollbar”。 3.将Scrollbar改名为“ScrollbarHorizontal”。 4.在Inspector面板中,将Direction属性设置为“Left To Right”。 5.在Hierarchy面板中,右键点击“ScrollbarHorizontal”,并选择“Duplicate”。 6.将Scrollbar2改名为“ScrollbarVertical”。 7.在Inspector面板中,将Direction属性设置为“Top To Bottom”。 8.在Hierarchy面板中,右键点击“Create Empty”,并选择“UI->Panel”。 9.将Panel重命名为“ScrollView”。 10.在Inspector面板中,将ScrollView的RectTransform的Anchor Presets设置为“Stretch Stretch”。这会将ScrollView铺满整个屏幕。 11.在Hierarchy面板中,将“ScrollbarHorizontal”和“ScrollbarVertical”拖拽到“ScrollView”下。 12.在Inspector面板中,将“ScrollbarHorizontal”和“ScrollbarVertical”的RectTransform的Anchor Presets设置为“Top Stretch”和“Left Stretch”分别。 13.在Hierarchy面板中,右键点击“Create Empty”,并选择“UI->Image”。 14.将Image改名为“ScrollContent”。 15.在Inspector面板中,将ScrollContent的RectTransform的Anchor Presets设置为“Top Stretch”和“Left Stretch”分别。 16.在Hierarchy面板中,将ScrollContent拖拽到“ScrollView”下。 17.将ScrollContent的RectTransform的位置设为(0,0,0)。 18.在Inspector面板中,设置ScrollView的“Horizontal Scrollbar Visibility”和“Vertical Scrollbar Visibility”属性为“Auto Hide And Expand View”。 19.将ScrollView的RectTransform的大小设为(500,500)。 现在,您已经成功地在Unity中创建了一个Scroll View,并可以在其中滚动视口中浏览内容了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

司军礼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值