You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity2D实现Content RectTransform传送带式循环平滑滚动问题

解决Unity 2D内容传送带式循环滚动问题

我需要实现2D场景中Content的RectTransform平滑向右滚动,内容从右侧移出后从左侧重新进入,形成持续循环的传送带效果。尝试给Content挂载了以下脚本,但脚本仅能让内容向右移动一小段后就跳回初始位置,无法实现预期的循环滚动:

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

public class MovingContent : MonoBehaviour
{
    public RectTransform content;       // Reference to the Content RectTransform
    public float scrollSpeed = 5f;      // Speed at which the content scrolls
    private List<RectTransform> items;  // List to keep track of all the child items

    void Start()
    {
        // Initialize the list and populate it with the items
        items = new List<RectTransform>();
        for (int i = 0; i < content.childCount; i++)
        {
            items.Add(content.GetChild(i).GetComponent<RectTransform>());
        }
    }

    void Update()
    {
        // Move each item to the right
        foreach (RectTransform item in items)
        {
            item.anchoredPosition += Vector2.right * scrollSpeed * Time.deltaTime;
        }

        // Check if the first item has moved past the viewable area
        if (items[0].anchoredPosition.x > GetRightEdgeX(content))
        {
            // Calculate the width of the first item
            float itemWidth = items[0].sizeDelta.x;

            // Move the first item to the end of the list
            RectTransform firstItem = items[0];
            items.RemoveAt(0);
            items.Add(firstItem);

            // Place it on the left side of the last item
            RectTransform lastItem = items[items.Count - 2];
            firstItem.anchoredPosition = new Vector2(lastItem.anchoredPosition.x - itemWidth, lastItem.anchoredPosition.y);
        }
    }

    // Utility function to get the right edge X position of the RectTransform
    private float GetRightEdgeX(RectTransform rt)
    {
        return rt.anchoredPosition.x + rt.rect.width;
    }
}

问题分析

  1. 移出判断条件错误:原脚本用Content自身的右边缘作为判断标准,导致物品还没完全离开可视区域就被重置位置。正确的判断应该基于ScrollRect的Viewport右边缘。
  2. 位置重置逻辑错误:原代码将第一个物品移到倒数第二个物品左侧,没有考虑物品间距,且未基于可视区域左边缘计算位置,导致滚动时出现跳变。

修复后的脚本

using System.Collections.Generic;
using UnityEngine;

public class MovingContent : MonoBehaviour
{
    public RectTransform content;       // Content的RectTransform引用
    public RectTransform viewport;      // ScrollRect的Viewport引用
    public float scrollSpeed = 5f;      // 滚动速度
    private List<RectTransform> items;  // 子物品列表

    void Start()
    {
        items = new List<RectTransform>();
        // 初始化子物品列表
        for (int i = 0; i < content.childCount; i++)
        {
            items.Add(content.GetChild(i).GetComponent<RectTransform>());
        }
        // 初始排列物品(确保无缝衔接)
        ArrangeInitialItems();
    }

    void Update()
    {
        // 所有物品向右移动
        foreach (RectTransform item in items)
        {
            item.anchoredPosition += Vector2.right * scrollSpeed * Time.deltaTime;
        }

        // 检查第一个物品是否完全移出可视区域右侧
        RectTransform firstItem = items[0];
        float itemRightEdge = firstItem.anchoredPosition.x + firstItem.rect.width;
        float viewportRightEdge = viewport.anchoredPosition.x + viewport.rect.width;

        if (itemRightEdge > viewportRightEdge)
        {
            // 将第一个物品移到列表末尾
            items.RemoveAt(0);
            items.Add(firstItem);

            // 计算新位置:放在当前最后一个物品的左侧,保持间距
            RectTransform lastItem = items[items.Count - 2];
            float newX = lastItem.anchoredPosition.x - firstItem.rect.width;
            firstItem.anchoredPosition = new Vector2(newX, firstItem.anchoredPosition.y);
        }
    }

    // 初始排列物品,确保从左侧开始无缝排列
    private void ArrangeInitialItems()
    {
        float currentX = 0f;
        foreach (RectTransform item in items)
        {
            item.anchoredPosition = new Vector2(currentX, item.anchoredPosition.y);
            currentX += item.rect.width;
        }
    }

    // 可选:如果需要支持动态添加物品,可添加此方法
    public void AddItem(RectTransform newItem)
    {
        items.Add(newItem);
        RectTransform lastItem = items[items.Count - 2];
        newItem.anchoredPosition = new Vector2(lastItem.anchoredPosition.x + lastItem.rect.width, lastItem.anchoredPosition.y);
    }
}

使用说明

  • 确保Content的父物体是ScrollRect的Viewport,ScrollRect需开启Horizontal、关闭Vertical,并禁用Movement Type的弹性效果
  • 在Inspector面板中,给脚本赋值content和viewport的引用
  • 调整scrollSpeed参数控制滚动速度,数值越大滚动越快

内容的提问来源于stack exchange,提问作者Daniel Lip

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 22:30:31