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

Unity移动端商店按钮控制循环滚动系统实现方案咨询

移动端游戏商店滚动系统的纯代码实现方案

核心思路

放弃Scroll Rect,直接通过控制容器位置+UI元素管理实现滚动逻辑:用带遮罩的水平容器装载所有物品,点击左右按钮时通过代码调整容器的水平偏移量,同时保留一个重叠物品明确滚动方向;物品移除后直接更新列表并调整容器位置,逻辑更直观,避免Scroll Rect的偏移计算问题。

具体实现步骤

1. UI结构搭建

  • 带HorizontalLayoutGroup组件的容器:自动排列物品,支持设置间距
  • 左右滚动控制按钮:用于触发前后滚动逻辑
  • 外层Mask组件:仅显示指定区域(比如单次显示3个物品,第三个与下一个物品保留部分重叠)
  • 物品预制体:每个物品绑定购买按钮,点击触发移除逻辑

2. 核心变量与初始化

定义关键变量记录状态,初始化时统计物品列表、计算物品总宽度:

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

public class ShopScrollController : MonoBehaviour
{
    public HorizontalLayoutGroup itemContainer;
    public Button leftBtn;
    public Button rightBtn;
    public float overlapWidth = 50f; // 重叠元素宽度,用于明确滚动方向
    public int visibleItemCount = 3; // 单次可见物品数量

    private List<GameObject> itemList = new List<GameObject>();
    private float itemTotalWidth; // 单个物品+布局间距的总宽度
    private int currentStartIndex = 0; // 当前显示的起始物品索引

    void Start()
    {
        // 初始化物品列表
        foreach (Transform child in itemContainer.transform)
        {
            itemList.Add(child.gameObject);
        }
        // 计算单个物品的总宽度(物品宽度+布局间距)
        if (itemList.Count > 0)
        {
            RectTransform itemRect = itemList[0].GetComponent<RectTransform>();
            itemTotalWidth = itemRect.rect.width + itemContainer.spacing;
        }
        UpdateButtonStates();
    }
}

3. 滚动逻辑实现

点击按钮时计算目标偏移量,支持平滑/即时切换:

// 向右滚动按钮点击事件
public void OnRightBtnClick()
{
    int maxStartIndex = itemList.Count - visibleItemCount;
    if (currentStartIndex >= maxStartIndex) return;

    currentStartIndex++;
    // 计算容器目标位置(向左偏移,实现物品右滚效果)
    float targetPosX = -currentStartIndex * (itemTotalWidth - overlapWidth);
    // 平滑切换:用LeanTween/DOTween,直接赋值则为即时切换
    LeanTween.moveX(itemContainer.GetComponent<RectTransform>(), targetPosX, 0.3f);
    UpdateButtonStates();
}

// 向左滚动按钮点击事件
public void OnLeftBtnClick()
{
    if (currentStartIndex <= 0) return;

    currentStartIndex--;
    float targetPosX = -currentStartIndex * (itemTotalWidth - overlapWidth);
    LeanTween.moveX(itemContainer.GetComponent<RectTransform>(), targetPosX, 0.3f);
    UpdateButtonStates();
}

4. 物品移除逻辑

购买后移除物品,自动调整显示状态避免空白:

// 移除指定物品(绑定到物品的购买按钮)
public void RemoveItem(GameObject item)
{
    int removeIndex = itemList.IndexOf(item);
    if (removeIndex == -1) return;

    itemList.Remove(item);
    Destroy(item);

    // 如果移除的是当前显示范围内的物品,调整起始索引
    if (removeIndex < currentStartIndex + visibleItemCount)
    {
        currentStartIndex = Mathf.Max(currentStartIndex - 1, 0);
        // 刷新容器位置
        float targetPosX = -currentStartIndex * (itemTotalWidth - overlapWidth);
        itemContainer.GetComponent<RectTransform>().anchoredPosition = new Vector2(targetPosX, 0);
    }

    UpdateButtonStates();
}

5. 边界与数量限制

  • 按钮状态更新:滚动到首尾时自动隐藏对应按钮
  • 数量限制:添加物品时判断总数,最多8个
// 更新左右按钮显示状态
private void UpdateButtonStates()
{
    leftBtn.gameObject.SetActive(currentStartIndex > 0);
    bool isAtEnd = currentStartIndex + visibleItemCount >= itemList.Count;
    rightBtn.gameObject.SetActive(!isAtEnd);
}

// 添加物品(限制最多8个)
public void AddItem(GameObject itemPrefab)
{
    if (itemList.Count >= 8) return;

    GameObject newItem = Instantiate(itemPrefab, itemContainer.transform);
    itemList.Add(newItem);
    // 重新计算物品宽度(物品尺寸一致可跳过)
    RectTransform itemRect = newItem.GetComponent<RectTransform>();
    itemTotalWidth = itemRect.rect.width + itemContainer.spacing;
    UpdateButtonStates();
}

方案优势

  • 完全无需Scroll Rect,避免horizontalNormalizedPosition因物品数量变化导致的偏移异常
  • 物品移除逻辑更直接,自动调整显示状态,无需额外跟踪偏移值
  • 滚动步长由物品宽度和重叠宽度决定,适配不同尺寸的物品
  • 代码逻辑清晰,移动端性能开销低

内容的提问来源于stack exchange,提问作者Not Available

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 09:57:49