Unity中如何让ScrollView的Viewport始终居中?当前其偏左
问题:HorizontalScrollView Viewport无法自动居中(自定义ChiScrollRect脚本导致)
- 当前HorizontalScrollView的Viewport默认处于左侧位置,手动拖动红色区域可将其大致居中,但需要实现自动保持居中的效果
- 尝试按住Alt键选择锚点预设的Middle/Center,无法将Viewport设置为居中,问题根源在于挂载于HorizontalScrollView上的
ChiScrollRect脚本(该脚本用于解决「鼠标在ScrollView内的按钮上时无法通过滚轮滚动」的问题)
效果截图
- Viewport偏左状态:

- 目标居中效果:

- Content对象设置:

自定义ChiScrollRect脚本代码
using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; public class ChiScrollRect : ScrollRect, IPointerEnterHandler, IPointerExitHandler { private static string mouseScrollWheelAxis = "Mouse ScrollWheel"; private bool swallowMouseWheelScrolls = true; private bool isMouseOver = false; public void OnPointerEnter(PointerEventData eventData) { isMouseOver = true; } public void OnPointerExit(PointerEventData eventData) { isMouseOver = false; } private void Update() { // Detect the mouse wheel and generate a scroll. This fixes the issue where Unity will prevent our ScrollRect // from receiving any mouse wheel messages if the mouse is over a raycast target (such as a button). if (isMouseOver && IsMouseWheelRolling()) { var delta = UnityEngine.Input.GetAxis(mouseScrollWheelAxis); PointerEventData pointerData = new PointerEventData(EventSystem.current); pointerData.scrollDelta = new Vector2(0f, delta); swallowMouseWheelScrolls = false; OnScroll(pointerData); swallowMouseWheelScrolls = true; } } public override void OnScroll(PointerEventData data) { if (IsMouseWheelRolling() && swallowMouseWheelScrolls) { // Eat the scroll so that we don't get a double scroll when the mouse is over an image } else { // Amplify the mousewheel so that it matches the scroll sensitivity. if (data.scrollDelta.y < -Mathf.Epsilon) data.scrollDelta = new Vector2(0f, -scrollSensitivity); else if (data.scrollDelta.y > Mathf.Epsilon) data.scrollDelta = new Vector2(0f, scrollSensitivity); base.OnScroll(data); } } private static bool IsMouseWheelRolling() { return UnityEngine.Input.GetAxis(mouseScrollWheelAxis) != 0; } }
解决方案
1. 编辑器层面修正布局设置
- Viewport设置:选择Viewport对象,在RectTransform面板中,按住Alt点击「Middle Center」预设,确保锚点(Anchor)和轴心(Pivot)均为
(0.5, 0.5),位置(Position)设为(0, 0, 0),宽高与父级ScrollView保持一致 - Content设置:
- 如果使用
Horizontal Layout Group组件,将「Child Alignment」设为Middle Center,确保内容在Content内垂直居中 - 调整Content的RectTransform锚点:垂直方向设为
(0, 0.5, 0, 0.5),保证Content始终在ScrollView垂直居中;水平方向锚点设为(0, 0.5, 0, 0.5)或(0,0,0,0)(根据需求选择)
- 如果使用
2. 修改脚本添加初始化居中逻辑
在ChiScrollRect脚本中添加Start方法,初始化时自动将Content调整到居中位置,覆盖脚本可能导致的布局偏移:
private void Start() { // 仅针对HorizontalScrollView处理居中 if (!horizontal) return; float contentWidth = content.rect.width; float viewportWidth = viewport.rect.width; // 内容宽度大于视口时,计算居中偏移量;否则直接居中 float targetPosX = contentWidth > viewportWidth ? -(contentWidth - viewportWidth) / 2f : 0f; content.anchoredPosition = new Vector2(targetPosX, content.anchoredPosition.y); }
3. 修复脚本潜在的布局干扰
添加Reset方法,确保脚本重置时继承原生ScrollRect的默认属性,避免布局异常:
public override void Reset() { base.Reset(); // 重置为HorizontalScrollView的默认属性 horizontal = true; vertical = false; movementType = MovementType.Elastic; elasticity = 0.1f; }
内容的提问来源于stack exchange,提问作者Daniel Lip
相关产品推荐
相关产品推荐

