うにてぃブログ

主にUnityとC#に関する記事を書いていきます

【Unity】ScrollRect を使用して特定の要素までスクロールさせる方法

このクラスは、指定したインデックスの子オブジェクトを表示エリア内にスクロールする「ScrollTo」メソッドと、指定したRectTransformが表示エリア内に収まるようにスクロールする「ScrollTo」メソッドが実装されています。

これを利用することで、以下のように一部隠れているオブジェクトを全部表示させることができます

public static class ScrollRectExtension
{
    public static void ScrollTo(this ScrollRect self, int index)
    {
        var count = self.content.childCount;
        if (index < 0 || index >= count)
            return;

        var rect = self.content.GetChild(index).GetComponent<RectTransform>();
        if (rect == null)
            return;
        
        self.ScrollTo(rect);
    }
    
    public static void ScrollTo(this ScrollRect self, RectTransform child)
    {
        var vectorIndex = self.horizontal ? 0 : 1;
        var rect1 = self.viewport.rect;
        var rect2 = self.content.rect;
        
        var viewSize = new Vector2(rect1.width, rect1.height)[vectorIndex];
        var contentSize = new Vector2(rect2.width, rect2.height)[vectorIndex];
        var anchoredPosition = Mathf.Abs(self.content.anchoredPosition[vectorIndex]);
        var max = contentSize - viewSize;
        
        var childPosition = Mathf.Abs(child.anchoredPosition[vectorIndex]);
        var childSizeHalf = (new Vector2(child.rect.width, child.rect.height) / 2f)[vectorIndex];
        
        if (childPosition - childSizeHalf < anchoredPosition)
        {
            var value = childPosition - childSizeHalf - viewSize / 2f + childSizeHalf;
            ApplyAnchoredPosition(value);
        }
        else if (childPosition + childSizeHalf > anchoredPosition + viewSize)
        {
            var value = childPosition + childSizeHalf - viewSize + (viewSize - childSizeHalf * 2) / 2f;
            ApplyAnchoredPosition(value);
        }
        
        void ApplyAnchoredPosition(float value)
        {
            var pos = self.content.anchoredPosition;
            pos[vectorIndex] = Mathf.Clamp(value, 0, max) * (vectorIndex == 1 ? 1 : -1);
            self.content.anchoredPosition = pos;
        }        
    }
}