Unity 实现 ScrollBar 值变化控制 Panel 位置的方法

以下是几种实现 ScrollBar 值变化控制 Panel 位置的方法:

方法1:直接控制位置(推荐)

cs 复制代码
using UnityEngine;
using UnityEngine.UI;

public class ScrollController : MonoBehaviour
{
    [Header("UI References")]
    public Scrollbar scrollbar;
    public RectTransform panel; // 要移动的Panel
    
    [Header("Scroll Settings")]
    public float minYPosition = 0f;   // 最小Y位置
    public float maxYPosition = 100f; // 最大Y位置
    public bool horizontalScroll = false; // 是否水平滚动
    
    private void Start()
    {
        // 添加监听事件
        scrollbar.onValueChanged.AddListener(OnScrollbarValueChanged);
        
        // 初始化位置
        OnScrollbarValueChanged(scrollbar.value);
    }
    
    private void OnScrollbarValueChanged(float value)
    {
        if (panel == null) return;
        
        if (horizontalScroll)
        {
            // 水平滚动:控制X位置
            float newX = Mathf.Lerp(minYPosition, maxYPosition, value);
            panel.anchoredPosition = new Vector2(newX, panel.anchoredPosition.y);
        }
        else
        {
            // 垂直滚动:控制Y位置
            float newY = Mathf.Lerp(minYPosition, maxYPosition, value);
            panel.anchoredPosition = new Vector2(panel.anchoredPosition.x, newY);
        }
    }
    
    private void OnDestroy()
    {
        // 移除监听,防止内存泄漏
        if (scrollbar != null)
            scrollbar.onValueChanged.RemoveListener(OnScrollbarValueChanged);
    }
}

方法2:使用 ScrollRect(更简单)

cs 复制代码
using UnityEngine;
using UnityEngine.UI;

public class SimpleScrollController : MonoBehaviour
{
    public ScrollRect scrollRect;
    
    void Start()
    {
        // 自动获取或手动指定ScrollRect
        if (scrollRect == null)
            scrollRect = GetComponent<ScrollRect>();
    }
    
    // 外部调用更新滚动位置
    public void UpdateScrollPosition(float value)
    {
        if (scrollRect != null)
        {
            scrollRect.verticalNormalizedPosition = 1 - value; // 反转值(Unity的滚动方向)
        }
    }
}

方法3:平滑滚动效果

cs 复制代码
using UnityEngine;
using UnityEngine.UI;

public class SmoothScrollController : MonoBehaviour
{
    public Scrollbar scrollbar;
    public RectTransform panel;
    
    [Header("Smooth Settings")]
    public float smoothTime = 0.1f;
    public float maxYPosition = 100f;
    
    private float targetPosition;
    private float currentVelocity;
    
    private void Start()
    {
        scrollbar.onValueChanged.AddListener(OnScrollValueChanged);
    }
    
    private void OnScrollValueChanged(float value)
    {
        targetPosition = Mathf.Lerp(0, maxYPosition, value);
    }
    
    private void Update()
    {
        // 平滑过渡到目标位置
        float currentY = panel.anchoredPosition.y;
        float newY = Mathf.SmoothDamp(currentY, targetPosition, ref currentVelocity, smoothTime);
        
        panel.anchoredPosition = new Vector2(panel.anchoredPosition.x, newY);
    }
    
    private void OnDestroy()
    {
        if (scrollbar != null)
            scrollbar.onValueChanged.RemoveListener(OnScrollValueChanged);
    }
}

方法4:完整的双向滚动控制

cs 复制代码
using UnityEngine;
using UnityEngine.UI;

public class AdvancedScrollController : MonoBehaviour
{
    public Scrollbar horizontalScrollbar;
    public Scrollbar verticalScrollbar;
    public RectTransform contentPanel;
    
    [Header("Scroll Limits")]
    public Vector2 minPosition = Vector2.zero;
    public Vector2 maxPosition = new Vector2(100f, 100f);
    
    private void Start()
    {
        if (horizontalScrollbar != null)
            horizontalScrollbar.onValueChanged.AddListener(OnHorizontalScroll);
            
        if (verticalScrollbar != null)
            verticalScrollbar.onValueChanged.AddListener(OnVerticalScroll);
    }
    
    private void OnHorizontalScroll(float value)
    {
        float newX = Mathf.Lerp(minPosition.x, maxPosition.x, value);
        contentPanel.anchoredPosition = new Vector2(
            newX, 
            contentPanel.anchoredPosition.y
        );
    }
    
    private void OnVerticalScroll(float value)
    {
        float newY = Mathf.Lerp(minPosition.y, maxPosition.y, value);
        contentPanel.anchoredPosition = new Vector2(
            contentPanel.anchoredPosition.x, 
            newY
        );
    }
    
    // 更新滚动条值(当通过其他方式移动Panel时调用)
    public void UpdateScrollbarValues()
    {
        if (horizontalScrollbar != null)
        {
            float horizontalValue = Mathf.InverseLerp(
                minPosition.x, 
                maxPosition.x, 
                contentPanel.anchoredPosition.x
            );
            horizontalScrollbar.value = horizontalValue;
        }
        
        if (verticalScrollbar != null)
        {
            float verticalValue = Mathf.InverseLerp(
                minPosition.y, 
                maxPosition.y, 
                contentPanel.anchoredPosition.y
            );
            verticalScrollbar.value = verticalValue;
        }
    }
    
    private void OnDestroy()
    {
        if (horizontalScrollbar != null)
            horizontalScrollbar.onValueChanged.RemoveListener(OnHorizontalScroll);
        if (verticalScrollbar != null)
            verticalScrollbar.onValueChanged.RemoveListener(OnVerticalScroll);
    }
}

使用方法:

  1. 方法1:将脚本挂载到任意 GameObject,在 Inspector 中拖拽对应的 Scrollbar 和 Panel

  2. 方法2:直接使用 Unity 自带的 ScrollRect 组件

  3. 方法3:需要平滑滚动效果时使用

  4. 方法4:需要同时控制水平和垂直滚动时使用

注意事项:

  • 确保 Panel 的锚点设置正确

  • 调整 minPositionmaxPosition 来匹配你的实际需求

  • 使用 Mathf.Lerp 可以确保值在指定范围内平滑过渡

DEEP SEEK生成

相关推荐
jtymyxmz22 分钟前
《Unity Shader》12.6 运动模糊
unity·游戏引擎
jtymyxmz3 小时前
《Unity Shader》12.4.2 实现
unity·游戏引擎
sindyra5 小时前
Unity UGUI 之 Canvas Scaler
unity·游戏引擎
在路上看风景9 小时前
2.Square Grid
unity
程序猿阿伟9 小时前
《突破Unity热更新瓶颈:底层函数调用限制与生态适配秘籍》
unity·游戏引擎
龙智DevSecOps解决方案11 小时前
Perforce《2025游戏技术现状报告》Part 3:不同行业挑战以及Unreal、Godot、自研游戏引擎的应用趋势
游戏引擎·godot·游戏开发·perforce
在路上看风景11 小时前
13. UGUI合批
unity
jtymyxmz1 天前
《Unity Shader》12.2调整屏幕的亮度、饱和度和对比度
unity·游戏引擎
AllBlue1 天前
unity嵌入安卓界面,如何显示状态
android·unity·游戏引擎
tealcwu1 天前
【Unity技巧】实现在Play时自动保存当前场景
java·unity·游戏引擎