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生成

相关推荐
Longyugxq15 小时前
Untiy的Webgl端网页端视频播放,又不想直接mp4格式等格式的。
unity·音视频·webgl
avi911117 小时前
Unity毛玻璃渲染模糊渲染Shader数学入门
unity·aigc·图形学·shader·hlsl
微光守望者18 小时前
Unity小知识【1】:刚体(Rigidbody)与碰撞器(Collider)的区别,你真的清楚吗?
unity·游戏引擎
孟无岐19 小时前
【Laya】Byte 二进制数据处理
网络·typescript·游戏引擎·游戏程序·laya
孟无岐21 小时前
【Laya】ClassUtils 类反射工具
typescript·游戏引擎·游戏程序·laya
June bug1 天前
【配环境】unity项目开发环境
unity·游戏引擎
JQLvopkk1 天前
C#调用Unity实现设备仿真开发浅述
开发语言·unity·c#
秦奈1 天前
Unity复习学习笔记(九):UGUI
笔记·学习·unity
李尚朋20211 天前
搜嗖工具箱|小众有个性的趣味网站合集
深度学习·搜索引擎·游戏引擎
垂葛酒肝汤1 天前
unity的背包滑动组件中道具的提示框被裁剪的问题
unity·游戏引擎