unity——滚动显示数据列表

本文详细介绍了在Unity3D中如何创建一个轮播信息系统,包括数据结构的定义,如`MessageDatas`、`Item`和`ScrollSet`,以及使用协程获取和显示轮播内容的实现。通过`ScrollList`类展示了如何从服务器获取JSON数据,解析并更新消息队列,最后实现文本的动态滚动展示。同时,还提及了Unity中的遮罩和文本父物体的设置,确保轮播效果的正常显示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、脚本设置 

1、使用到数据结构类型
using TMPro;
using System;
using UnityEngine;
using System.Collections.Generic;

/// <summary>
/// 轮播数据
/// </summary>
[Serializable]
public class MessageDatas
{
    public bool success;
    public string message;
    public List<Item> items;
}
/// <summary>
/// 具体轮播内容
/// </summary>
[Serializable]
public class Item
{
    public string inform;
    ...
    ...
    ...
}
/// <summary>
/// 轮播设置
/// </summary>
[Serializable]
public class ScrollSet
{
    //对于一条信息:包含信息的文本在初始位置生成,
    //生成后移动到显示位置显示,一段时间后移动到结束位置销毁;
    public Vector2 endPos;//文本结束位置
    public Vector2 targetPos;//文本显示位置
    public Vector2 startPos;//文本生成初始位置

    public float scrollSpeed = 5;//文本移动速度
    public float stayTime = 5;//当前文本显示/停留时间
    public RectTransform textParent;//文本的父物体
    public TMP_Text textPrefab;//文本预制体
    public Queue<string> messageQueue = new Queue<string>();//信息队列
    public TMP_Text curText { get; set; }//当前显示的文本
    public TMP_Text nextText { get; set; }//下一个显示的文本
}
2、获取轮播显示的数据
using TMPro;
using System;
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
using System.Collections.Generic;

public class ScrollList : MonoBehaviour
{
    public string host;
    public string url;

    public ScrollSet scrollSet =new ScrollSet();
    public ScrollSet scrollSet2 = new ScrollSet();

    void OnEnable()
    {
        StartCoroutine("GetMessage", scrollSet);
    }

    ...
    ...
    ...

    //使用协程每隔一段时间获取更新信息一次
    IEnumerator GetMessage(ScrollSet scrollSet)
    {
        //更新获取信息的地址
        yield return new WaitUntil(() => !string.IsNullOrEmpty(host));
        StopCoroutine("ScrollInform");
        StartCoroutine("ScrollInform", scrollSet);
        string _url = string.Concat(host, url);
        //获取信息
        while (true)
        {
            UnityWebRequest unityWebRequest = new UnityWebRequest(_url);
            unityWebRequest.downloadHandler = new DownloadHandlerBuffer();
            yield return unityWebRequest.SendWebRequest();
            if (unityWebRequest.error == null)
            {
                //Debug.Log(unityWebRequest.downloadHandler.text);
                //将获取到的数据,转换为MessageDatas格式,并获取MessageDatas里的items数据,
                //并把items数据存到newMessages列表里
                List<Item> newMessages = JsonUtility.FromJson<MessageDatas>(unityWebRequest.downloadHandler.text).items;

                //遍历列表,把一条条数据放进队列里
                for (int i = 0; i < newMessages.Count; i++)
                {
                    if (!scrollSet.messageQueue.Contains(newMessages[i].inform)) scrollSet.messageQueue.Enqueue(newMessages[i].inform);
                }
                //结束请求
                unityWebRequest.Dispose();
            }
            else
            {
                Debug.Log(unityWebRequest.responseCode);
                Debug.Log(unityWebRequest.error);
                unityWebRequest.Dispose();
            }
            //隔段时间再次执行协程,获取数据
            yield return new WaitForSeconds(60f);
        }
    }
    
    ...
    ...
    ...
}
3,根据轮播设置,实现数据的轮播
using TMPro;
using System;
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
using System.Collections.Generic;

public class ScrollList : MonoBehaviour
{
    ...
    ...
    ...

    /// <summary>
    /// 滚动显示
    /// </summary>
    /// <returns></returns>
    IEnumerator ScrollInform(ScrollSet scrollSet)
    {
        //队列里有可以轮播的数据
        yield return new WaitUntil(() => scrollSet.messageQueue.Count > 0);
        
        //如果当前文本不存在,实例化出文本,并显示位置/目标位置直接显示出来
        if (!scrollSet.curText)
        {
            scrollSet.curText = Instantiate(scrollSet.textPrefab, scrollSet.textParent);
            scrollSet.curText.text = scrollSet.messageQueue.Dequeue();
            scrollSet.curText.rectTransform.anchoredPosition = scrollSet.targetPos;
        }
        while (true)
        {
            //根据轮播设置里的文本显示时间,显示当前文本
            yield return new WaitForSeconds(scrollSet.stayTime);
            //生成下一条显示的文本
            if (scrollSet.messageQueue.Count > 0)
            {
                if (!scrollSet.nextText) scrollSet.nextText = Instantiate(scrollSet.textPrefab, scrollSet.textParent);
                //设置文本值和初始位置
                scrollSet.nextText.text = scrollSet.messageQueue.Dequeue();
                scrollSet.nextText.rectTransform.anchoredPosition = scrollSet.startPos;
            }

            //除非现在的文本接近结束位置,或下个显示的文本接近目标位置/显示位置
            while (Mathf.Abs(scrollSet.endPos.y - scrollSet.curText.rectTransform.anchoredPosition.y) >= 0.01f || Mathf.Abs(scrollSet.targetPos.y - scrollSet.nextText.rectTransform.anchoredPosition.y) >= 0.01f)
            {
                //持续将当前文本和下个文本移动到指定位置
                scrollSet.curText.rectTransform.anchoredPosition = Vector2.Lerp(scrollSet.curText.rectTransform.anchoredPosition, scrollSet.endPos, Time.deltaTime * scrollSet.scrollSpeed);
                scrollSet.nextText.rectTransform.anchoredPosition = Vector2.Lerp(scrollSet.nextText.rectTransform.anchoredPosition, scrollSet.targetPos, Time.deltaTime * scrollSet.scrollSpeed);
                yield return null;
            }
            //将当前文本和下个文本位置更新到指定位置
            scrollSet.curText.rectTransform.anchoredPosition = scrollSet.endPos;
            scrollSet.nextText.rectTransform.anchoredPosition = scrollSet.targetPos;
            //销毁当前文本
            Destroy(scrollSet.curText.gameObject);
            //将下个文本设为当前文本
            scrollSet.curText = scrollSet.nextText;
            //清空当前文本
            scrollSet.nextText = null;
            //轮播完,重新获取数据
            if (scrollSet.messageQueue.Count == 0)
            {
                StopCoroutine("GetMessage");
                StartCoroutine("GetMessage", scrollSet);
                break;
            }
        }
    }

    ...
    ...
    ...
}

二、unity——轮播对象设置

1、轮播管理控制

2、遮罩,仅看得到显示位置的内容

3、设置文本父物体下面的文本位置

### 创建和优化无限滚动列表 #### 使用 EnhancedScroller 插件 为了在 Unity 中实现高效的无限滚动列表,可以利用 `EnhancedScroller` 插件。此工具专为处理大型数据集而设计,能够显著提升性能表现,适用于各种需要展示众多条目的界面组件,比如游戏内部的商品清单或是社交应用的消息记录等[^1]。 ```csharp // 示例:设置 EnhancedScroller 的基本配置 using UnityEngine; using UnityEngine.UI; public class ScrollerExample : MonoBehaviour { private void Start() { // 获取 EnhancedScroller 组件实例 var scroller = GetComponent<EnhancedScroller>(); // 设置每项的高度或其他属性 scroller.itemSize = 50f; // 注册回调函数来绘制每一项的内容 scroller.onInitializeItem += OnInitializeItem; } private void OnInitializeItem(EnhancedScrollListItem item, int dataIndex) { // 实现具体的布局更新逻辑... } } ``` #### 应用 UIS 扩展库 另一种解决方案是采用专门为 `ScrollRect` 定制的无限滚动增强包——UIS。该方案不仅解决了传统方式下可能出现的卡顿现象,还提供了更加平滑自然的操作体验给最终用户[^2]。 ```csharp // 示例:集成 UIS 到现有项目中 void SetupInfiniteScrolling() { // 初始化 UIS 并关联到目标 ScrollRect 上 InfiniteScroll infiniteScroll = new InfiniteScroll(scrollRect); // 配置预加载区域大小以及每次加载的新元素数量 infiniteScroll.PreloadZoneHeight = 300f; infiniteScroll.ItemsPerLoadBatch = 10; } // 当新一批次的数据准备就绪时触发的方法 infiniteScroll.OnItemsLoaded += (items) => { /* 更新 UI */ }; ``` #### 结合 ScrollView 和自定义脚本 对于更灵活的需求,则可以直接基于内置的 `ScrollView` 构建定制化的无限滚动机制。这通常涉及到手动管理可视范围内项目的生命周期及其位置调整,同时确保良好的交互响应速度[^4]。 ```csharp // 自定义无限列表控制器 public class CustomInfiniteListController : MonoBehaviour { public GameObject listItemPrefab; // 单元格预制体 private RectTransform contentRectTransform; private List<GameObject> activeCells = new List<GameObject>(); private void UpdateVisibleCells(float scrollPosition) { foreach (var cell in GetCellsInViewPort(scrollPosition)) { if (!activeCells.Contains(cell.gameObject)) InstantiateCellAt(cell.index); } CleanupOffscreenCells(); } private void InstantiateCellAt(int index){ var go = Instantiate(listItemPrefab, transform); ConfigureCell(go, GetDataForIndex(index)); activeCells.Add(go); } private IEnumerable<CellInfo> GetCellsInViewPort(float positionOffset){ // 计算当前可见范围内的单元格索引集合 yield break; } private void CleanupOffscreenCells(){ // 移除超出屏幕外的对象以节省资源 } } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值