(유니티) 자동 스크롤

Unity가 자동으로 플레이어에게 긴 기사를 표시하는 경우. B. 기사나 콘텐츠를 보려면 크레딧이 자동으로 스크롤되어야 합니다. 이를 가능하게 하기 위해 자동 스크롤 기능을 구현하고 구성했습니다.

소개

  • 스크롤 보기 영역을 자동으로 스크롤합니다.
  • 스크롤링 뷰의 콘텐츠 크기와 상관없이 일정한 속도로 자동 스크롤을 사용할 수 있습니다.
  • 런타임 중에 콘텐츠 영역의 크기가 변경되더라도 일정한 속도가 보장됩니다.

구현(스크립트 작성)

· AutoScroll.cs

더보기

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

public class AutoScroll : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
    (Header("자동으로 스크롤 할 양(width 또는 height)"))
    (SerializeField) private float mScrollSpeed = 0.1f;  // 스크롤 속도

    (Header("자동 스크롤을 시작할 딜레이 시간"))
    (SerializeField) private float mScrollDelay = 2f;  // 자동 스크롤 시작 딜레이

    (Header("세로 방향의 스크롤인가?"))
    (SerializeField) private bool mIsVerticalScroll;

    (Header("직접 스크롤 할 대상의 트랜스폼"))
    (SerializeField) private RectTransform mScrollRectTransform;

    private ScrollRect mScrollRect;  // 스크롤 영역
    private Coroutine? mCoAutoScroll; // 자동 스크롤 코루틴
    private bool mIsPointerEnter = false; // 현재 포인터가 영역에 들어왔는가?

    private void Awake()
    {
        mScrollRect = GetComponent<ScrollRect>();
    }

    private void OnEnable()
    {
        ToggleAutoScroll(true);
    }


    private void OnDisable()
    {
        ToggleAutoScroll(false);
    }

    private void ToggleAutoScroll(bool isEnable)
    {
        mScrollRect.velocity = Vector2.zero;

        if (mCoAutoScroll is not null)
            StopCoroutine(mCoAutoScroll);

        if (isEnable)
        {
            mCoAutoScroll = StartCoroutine(CoAutoScroll());
            mIsPointerEnter = false;
        }
    }

    private IEnumerator CoAutoScroll()
    {
        yield return new WaitForSecondsRealtime(mScrollDelay);

        while (true)
        {
            // 스크롤 방향에 따라 계산
            if (mIsVerticalScroll)
                mScrollRect.verticalNormalizedPosition -= mScrollSpeed * Time.deltaTime / mScrollRectTransform.sizeDelta.y;
            else
                mScrollRect.horizontalNormalizedPosition -= mScrollSpeed * Time.deltaTime / mScrollRectTransform.sizeDelta.x;

            // 스크롤의 끝 영역에 도달했다면 방향을 반전
            if ((mIsVerticalScroll ? mScrollRect.verticalNormalizedPosition : mScrollRect.horizontalNormalizedPosition) <= 0f || (mIsVerticalScroll ? mScrollRect.verticalNormalizedPosition : mScrollRect.horizontalNormalizedPosition) >= 1f)
                mScrollSpeed = -mScrollSpeed;

            // 영역에 포인터가 진입한 상태에서 클릭 또는 드래그를 했다면?
            if (mIsPointerEnter && (Input.GetMouseButton(0) || Input.GetAxis("Mouse ScrollWheel") > 0))
                ToggleAutoScroll(false);

            yield return null;
        }
    }

    public void OnPointerEnter(PointerEventData eventData)
    {
        mIsPointerEnter = true;
    }

    public void OnPointerExit(PointerEventData eventData)
    {
        mIsPointerEnter = false;
        ToggleAutoScroll(true);
    }
}

private IEnumerator CoAutoScroll()
  • 스크롤 영역을 자동으로 스크롤합니다.
  • 스크롤 방향에 따라 verticalNormalizedPosition 또는 horizontalNormalizedPosition의 값을 조정하여 스크롤 위치를 변경합니다.
  • mScrollRectTransform.sizeDelta의 크기로 나누어 스크롤 뷰의 콘텐츠 크기에 관계없이 동일한 속도로 스크롤할 수 있도록 합니다.
  • 또한 이 기능은 런타임 동안 실시간으로 변경되는 크기에 적응하여 동일한 속도로 유지합니다.

public void OnPointerEnter(PointerEventData eventData)
{
    mIsPointerEnter = true;
}
  • 커서나 사용자의 터치가 스크롤 보기 영역에 진입하면 mIsPointerEnter를 활성화하여 포인터를 입력된 상태로 설정합니다.
  • 이 값이 true이면 사용자가 코루틴을 중지하기 위해 마우스를 클릭(또는 터치)하거나 스크롤하면 코루틴이 자동 스크롤을 중지합니다.

신청방법


  • ScrollRect 구성 요소가 있는 Scroll View 객체에서 AutoScroll 스크립트를 사용합니다.
  • mScrollRectTransform은 가로 및 세로 길이를 참조하는 데 사용되며 Content 변환을 사용합니다.
  • 스크롤 뷰가 가로인지 세로인지 지정합니다.
  • 자동 스크롤 양을 설정하고 스크롤 시작 지연 시간을 설정합니다.

결과

  • 위 영상에서 보듯이 정상적인 조건에서는 자동으로 스크롤 됩니다.
  • 스크롤 영역의 끝에 도달하면 스크롤 방향이 반전됩니다.
  • 자동 스크롤 중에 플레이어가 직접 스크롤하면 자동 스크롤이 중지되고 사용자의 마우스 포인터가 스크롤 뷰포트를 벗어나면 자동 스크롤이 다시 시작되는 것을 볼 수 있습니다.