일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 프로그래머스
- soundmanager
- 유니티
- 직렬화
- Generic
- LINQ
- 코루틴
- skybox
- 자료구조
- script
- inputsystem
- 스택
- BGM
- 장애물달리기
- 람다식
- delegate
- FSM
- UI
- invokec#events
- 비선형자료구조
- unity
- 유한상태머신
- 배열
- 메서드
- 효과음
- 인터페이스
- c#
- 스파르타내일배움캠프
- InputManager
- ObjectPool
- Today
- Total
Unity 개발일지
[Unity] Scroll View를 이용한 화면전환 본문

모바일 게임을 기획하던 중 화면을 Swipe 해서 보여주는 방식에 대해 고민을 해보았다.
1. World Space에 맞춘 Canvas 구성
[장점]
1. 카메라가 직관적으로 이동하여 몰입감이 강함
2. 월드 공간에서 카메라의 이동을 자유롭게 제어 가능
3. 2D 환경에 적합
[단점]
1. UI가 월드 좌표에 배치되어 UI관리가 복잡
2. 2D UI보다 렌더링 성능에 더 많은 자원을 사용
3. UI를 World Canvas에 대응시키려면 너무 작은 화면에 대응해야 함
2. Scroll View를 이용한 입력을 감지하고, 카메라가 따라가도록 코딩하여 장면전환
[장점]
1. 스와이프나 터치 제스처를 총해 자연스러운 화면 전환
2. 간편한 구현
3. 다양한 해상도에서 일관된 사용자 경험 제공
[단점]
1. UI요소의 렌더링에 따른 성능 저하 발생
2. UI와 카메라의 충돌
3. 스크롤 영역과 카메라 연동의 복잡도
1번 방법의 단점 3번이 너무 크기 때문에 2번방법을 선택하게 되었다.

먼저 Canvas에 Scroll View를 Object를 생성해준 후 Scrollbar Horizontal과 Vertical은 사용하지 않을 예정이기 때문에 삭제해주었다. Content 안에는 각각의 왼쪽, 중앙, 오른쪽의 UI를 넣어주었다.

Scroll View의 Scroll Rect 컴포넌트는 좌우 입력만 감지하기 위해 Horizontal만 체크해주었고,
Movement Type은 원하는 흔들림을 없애기 위해 Clamped를 사용하였다.


CameraController 스크립트 참고
using UnityEngine;
public class CameraController : MonoBehaviour
{
[SerializeField] private float[] targetPositions = { -5.72f, 0f, 5.72f };
[SerializeField] private float moveSpeed = 5f;
private int currentIndex = 1; // 초기 위치 (0: 왼쪽, 1: 중앙, 2: 오른쪽)
private Vector2 startTouchPosition;
private Vector2 endTouchPosition;
private bool isMoving = false;
private void Start()
{
transform.position = new Vector3(0f, 0f, -10f);
currentIndex = 1;
}
private void Update()
{
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
{
startTouchPosition = Input.GetTouch(0).position;
}
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Ended)
{
endTouchPosition = Input.GetTouch(0).position;
HandleSwipe();
}
// 마우스 드래그 지원 (에디터 테스트용)
if (Input.GetMouseButtonDown(0))
{
startTouchPosition = Input.mousePosition;
}
if (Input.GetMouseButtonUp(0))
{
endTouchPosition = Input.mousePosition;
HandleSwipe();
}
// 카메라 이동 처리
if (isMoving)
{
float targetX = targetPositions[currentIndex];
Vector3 newPosition = new Vector3(
Mathf.Lerp(transform.position.x, targetX, Time.deltaTime * moveSpeed),
transform.position.y,
-10f
);
transform.position = newPosition;
// 일정 거리 이하로 접근하면 이동 완료 처리
if (Mathf.Abs(transform.position.x - targetX) < 0.01f)
{
transform.position = new Vector3(targetX, transform.position.y, -10f);
isMoving = false;
}
}
}
private void HandleSwipe()
{
float swipeDistance = endTouchPosition.x - startTouchPosition.x;
if ((Mathf.Abs(swipeDistance) > 200)) // 스와이프 감도 조절 (200px 이상 이동 시 인식)
{
if (swipeDistance < 0 && currentIndex < targetPositions.Length - 1) // 오른쪽으로 스와이프
{
currentIndex++;
isMoving = true;
}
else if (swipeDistance > 0 && currentIndex > 0) // 왼쪽으로 스와이프
{
currentIndex--;
isMoving = true;
}
}
}
// 현재 카메라 위치 인덱스 반환
public int GetCurrentIndex()
{
return currentIndex;
}
// 카메라 이동 가능 위치 배열 반환
public float[] GetTargetPositions()
{
return targetPositions;
}
}
Content에 등록한 SwipeUI 스크립트이다.
InitializePagesPositions 메서드에서는
Camera의 targetPositions를 가져와 배열의 Length를 이용해페이지의 개수를 정해주었고, 초기 위치를 설정해주었다.
Update문에서 입력관련 감지를 했고, lerpSpeed 변수로 카메라가 UI를 쫒아 이동하도록 설정해주었다.
UpdateScrollWithCamera 스크립트에서는 CameraController의 GetCurrentIndex 메서드를 이용해 현재 카메라 인덱스를 얻고, 이를 기반으로 targetPosition을 업데이트하여 ScrollRect를 해당 페이지로 이동시켜주었다.

해당 스크립트로 드래그를 할 때 카메라가 움직이고 UI가 유동적으로 움직이는 느낌을 줄 수 있었지만 깔끔하지 않았다.

Swipe 효과 적용이 완료된 모습이다.
오브젝트들이 고정되어있지 않고 함께 움직였던 이유는 UI가 아닌 World Space에 배치된 오브젝트였기 때문인데,
이것들을 Canvas에 UI화 시켜 배치하여 직관적인 효과도 챙길 수 있었다.
'Unity 개발' 카테고리의 다른 글
[Unity] Behaviour Tree 이론편 (0) | 2024.07.29 |
---|---|
[Unity] 네트워크 이론 (0) | 2024.07.24 |
[Unity] 멀티스레드(Thread) & GPU (1) | 2024.07.23 |
[Unity] Json과 직렬화 실습하기 (0) | 2024.07.22 |
[Unity] 최적화 실습하기 (1) | 2024.07.17 |