Unity-ScrollRect扩展

Unity-ScrollRect扩展

功能点简单说明

在原有的ScrollRect组件的基础上进行扩展:
1. 内部维护有对象池
2. 可以使用有限的子物体实现无限量的数据展示
3. 内部写有接口类,方便扩展

功能预览

屏幕录制 2023-12-07 162714

组件属性

组件属性

代码

MyScrollRect.cs

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

namespace SH
{
	/// <summary>
	/// 滑动列表子物体的控件接口
	/// </summary>
	/// <typeparam name="DataType"></typeparam>
    public interface IDataControllerType<DataType>
    {
        void Init(int index, DataType data);
    }

    /// <summary>
    /// 自定义滑动窗口组件
    /// 只需要创建少量组件,即可完成大量数据展示(不采用翻页形式)</summary>
    /// 支持上下滑动
    /// 非继承MonoBehaviour类
    /// <typeparam name="DataType">数据</typeparam>
    /// <typeparam name="DataControllerType">UI控件类(需要继承IDataControllerType接口)</typeparam>
    [System.Serializable]
    public class MyScrollView<DataType, DataControllerType> : IDisposable where DataControllerType : MonoBehaviour, IDataControllerType<DataType>
    {
        [Tooltip("预生成的预制物数量"), ReadOnly]
        public int dataCount = 18;
        [Tooltip("当前窗口最大展示数量")]
        public int curShowMaxCout = 16;
        [Tooltip("滑动窗口的预制物")]
        public GameObject prefab_data;
        [Tooltip("滑动窗口组件")]
        public ScrollRect scrollRect;
        [Tooltip("垂直滑动条")]
        public Scrollbar scrollbar;

        public List<DataType> dataList = new();              //当前可以展示的数据集合
        List<DataControllerType> dataControllerList = new(); //当前所有控件

        float orcVal = 1;
        int minIndex = 0;
        int maxIndex = 0;

        public MyScrollView()
        {
            dataCount = curShowMaxCout + 2;
        }


        public void Dispose()
        {
            dataList.Clear();
            dataList = null;

            for (int i = 0; i < dataControllerList.Count; i++)
            {
                GameObject.Destroy(dataControllerList[i].gameObject);
            }
            dataControllerList.Clear();
            dataControllerList = null;
        }

        bool isInit = false;
        public void Init() 
        {
            if(isInit) return;

            isInit = true;

            Check();
            scrollbar.onValueChanged.AddListener(UpdataPeoples);
            UpdataPeoples(1);
        }

        void Check()
        {
            Assert.IsTrue(dataCount >= curShowMaxCout + 2);
            Assert.IsTrue(prefab_data != null);
            Assert.IsTrue(scrollRect != null);
            Assert.IsTrue(scrollbar != null);
        }


        void UpdataPeoples(float val)
        {
            if (dataControllerList.Count <= 0)
            {
                for (int i = 0; i < dataCount; i++)
                {
                    GameObject go = GameObject.Instantiate(prefab_data);
                    go.transform.SetParent(scrollRect.content, false);
                    var controller = go.AddComponent<DataControllerType>();

                    dataControllerList.Add(controller);
                }
            }

            if (dataList == null || dataList.Count <= dataCount)
            {
                for (int i = 0; i < dataCount; i++)
                {
                    if (dataList.Count > i)
                    {
                        dataControllerList[i].gameObject.SetActive(true);
                        dataControllerList[i].Init(i + 1, dataList[i]);
                    }
                    else
                    {
                        dataControllerList[i].gameObject.SetActive(false);
                    }
                }
                return;
            }
            else
            {
                float curDataSize = scrollbar.size;
                if (val == -1)
                {
                    orcVal = 1;
                    scrollRect.content.anchorMin = Vector2.zero;

                    for (int i = 0; i < dataCount; i++)
                    {
                        dataControllerList[i].Init(i + 1, dataList[i]);
                    }
                    minIndex = 1;
                    maxIndex = Math.Min(dataCount, dataControllerList.Count);
                    return;
                }

                int start = 0;
                int last = dataCount - 1;

                float size = scrollbar.size;
                while (true)
                {
                    //处理滑动效果(移动content组件)
                    float offset = val - orcVal;
                    if (Math.Abs(offset) < size)
                    {
                        scrollRect.content.anchoredPosition -= new Vector2(0, 50 * offset / size);
                        orcVal += offset;
                    }
                    else
                    {
                        scrollRect.content.anchoredPosition -= new Vector2(0, offset > 0 ? 50 : -50);
                        orcVal += size * (offset > 0 ? 1 : -1);
                    }

                    //处理子物体位置,保证持续移动后,子物体位置正确
                    float curContentY = scrollRect.content.anchoredPosition.y;
                    if (curContentY >= 50 && maxIndex < dataList.Count)
                    {
                        var startData = dataControllerList[start];
                        dataControllerList.RemoveAt(start);
                        startData.transform.SetAsLastSibling();
                        dataControllerList.Add(startData);

                        int newIndex = maxIndex;
                        if (newIndex < dataList.Count)
                        {
                            startData.Init(newIndex + 1, dataList[newIndex]);
                            scrollRect.content.anchoredPosition -= new Vector2(0, 50);
                            maxIndex += 1;
                            minIndex += 1;
                        }
                    }
                    else if (curContentY < 0 && minIndex > 0)
                    {
                        var lastData = dataControllerList[last];
                        dataControllerList.RemoveAt(last);
                        lastData.transform.SetAsFirstSibling();
                        dataControllerList.Insert(0, lastData);

                        int newIndex = minIndex;
                        if (newIndex >= dataCount - curShowMaxCout)
                        {
                            lastData.Init(newIndex - 1, dataList[newIndex - dataCount + curShowMaxCout]);
                            scrollRect.content.anchoredPosition -= new Vector2(0, -50);

                            maxIndex -= 1;
                            minIndex -= 1;
                        }
                    }

                    if (Math.Abs(val - orcVal) < 0.01f)
                    {
                        break;
                    }
                }
            }
        }
		/// <summary>
		/// 更新数据集合,刷新列表
		/// </summary>
		/// <param name="dataList">新的数据源</param>
        public void FlushDataList(ref List<DataType> dataList)
        {
            Init();
            this.dataList.Clear();
            this.dataList.AddRange(dataList);

            UpdataPeoples(1);
        }
    }
}

使用

1. 添加一个滑动列表子物体的控件类(继承 IDataControllerType 接口)

//替换DataType为自己有的类名或者结构体名
public class DataController: MonoBehaviour, IDataControllerType<DataType>
{
	/*
	UI 组件
	*/
	void Awake()
	{
		/*
		UI 组件初始化
		*/
	}
	public void Init(int index, DataType data)
	{
		/*
		用data的数据给 UI 组件赋值
		*/
	}
}

2.添加一个MyScrollView对象

//替换DataType为自己有的类名或者结构体名(与上面保持一致)
MyScrollView<DataType, DataController> scrollView = new MyScrollView<DataType, DataController>();

3.UI设置

关于ScrollRect部分的UI,是按照常规的UI布局来得
在这里插入图片描述
这个是控件类的属性贴图
组件属性

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Vue-Unity-WebGL 是一个具有极高可扩展性和灵活性的 Unity3D web 端开发框架,它将 Vue.js 与 Unity Web Player 和 WebGL 等技术相结合,为开发者提供了最佳的解决方案。 Vue-Unity-WebGL 框架具有很高的兼容性和易用性,开发者可以更加灵活地应用该框架来定制自己的项目。由于该框架具备了许多优秀的特性,如自适应布局、多平台支持等,使得开发者可以轻松地实现用户体验和开发效率的提升。此外,Vue-Unity-WebGL 框架不仅提供了可视化开发工具,还提供了完整的运行环境,为开发者提供了优秀的开发体验。 Vue-Unity-WebGL 框架的另一个重要特点是其大量的插件与扩展功能,这些插件和扩展可以为项目的开发和管理提供坚强的技术支持。比如,通过 vue-router 可以控制路由,Vue-Unity-WebGL 可以协作处理组件数据和 Unity3D 渲染等复杂的操作,而 Vuex 则可以使开发者方便地处理应用数据流和组件状态的管理。这些插件和扩展功能极大地提高了 Vue-Unity-WebGL 框架的可扩展性和灵活性,使得开发者可以更加容易地进行定制。 综上所述,Vue-Unity-WebGL 框架是一个快速、可靠且强大的解决方案,这使得开发者能够轻松地编写出高质量的 Unity3D web 应用程序。该框架具有大量的功能,实现可扩展性、灵活性、易用性和可维护性,比其他框架更具有竞争力。在未来的发展中,Vue-Unity-WebGL 框架将会被更多的开发者喜爱和应用,并在技术社区中拥有更广泛的影响力。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值