오늘 구현해볼 것은 Text가 자동으로 슬라이딩 되는 기능이다.
새로 추가된 업데이트나 새로운 소식을 사용자에게 제공해야 할 때 쓰면 유용 할 것 같다.
1. 하이어라키 세팅하기
먼저 Canvas 안에 새로운 Text 2개를 생성한다. 생성한 text는 동일한 Transform에 배치한다.
TodayNews오브젝트는 News Text 부모로 있는 뒤에 있는 배경이미지이다.
2. 코드 작성 및 설명
※ 변수 선언
[Header("Text Objects")]
public RectTransform textA; //News1
public RectTransform textB; //News2
[Header("Animation Settings")]
public float switchInterval = 2f; // 몇초마다 슬라이드 할지
public float slideDuration = 0.5f; // 몇초동안 슬라이드 될지
public float slotHeight = 100f; //얼마나 위로 Text를 옮길지
//내부 상태
private bool isTextAOnTop = true;
TextObjects -> Text 2개의 위치를 받아올 2개의 RectTransform을 선언
Animation Settings -> 주석 설명
※ Start 함수
private void Start()
{
// 초기 위치 설정
if (textA != null) textA.anchoredPosition = Vector2.zero;
if (textB != null) textB.anchoredPosition = new Vector2(0, slotHeight);
StartCoroutine(SlotMachineRoutine());
}
textA부터 시작, textB는 slotHeight만큼 위로 옮김(보이지않도록)
SlotMachineRoutine() 코루틴 함수 실행
※ SlotMachineRoutine() 코루틴 함수
private IEnumerator SlotMachineRoutine()
{
while (true)
{
yield return new WaitForSeconds(switchInterval);
RectTransform current = isTextAOnTop ? textA : textB;
RectTransform next = isTextAOnTop ? textB : textA;
//두 텍스트를 동시에 슬라이드
Coroutine slideCurrent = StartCoroutine(Slide(current, new Vector2(0, -slotHeight), slideDuration));
Coroutine slideNext = StartCoroutine(Slide(next, Vector2.zero, slideDuration));
//둘 다 완료될 때까지 대기
yield return slideCurrent;
yield return slideNext;
//내려간 텍스트를 다시 위로 올리기
current.anchoredPosition = new Vector2(0, slotHeight);
//상태 전환
isTextAOnTop = !isTextAOnTop;
}
}
textB가 TextA의 위치로 온 다음 TextA는 밑으로 내려간 후 다시 상단으로 올라가 내려갈 준비를 한다.
※ Slide 코루틴 함수
/// <summary>
/// RectTransform을 targetPos로 서서히 이동시키는 코루틴
/// </summary>
IEnumerator Slide(RectTransform rect, Vector2 targetPos, float duration)
{
Vector2 startPos = rect.anchoredPosition;
float elapsed = 0f;
while (elapsed < duration)
{
elapsed += Time.deltaTime;
float t = Mathf.Clamp01(elapsed / duration);
rect.anchoredPosition = Vector2.Lerp(startPos, targetPos, t);
yield return null;
}
rect.anchoredPosition = targetPos;
}
※ 전체코드
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System.Timers;
public class SlotMachineText : MonoBehaviour
{
[Header("Text Objects")]
public RectTransform textA;
public RectTransform textB;
[Header("Animation Settings")]
public float switchInterval = 2f;
public float slideDuration = 0.5f;
public float slotHeight = 100f;
//내부 상태
private bool isTextAOnTop = true;
private void Start()
{
// 초기 위치 설정
if (textA != null) textA.anchoredPosition = Vector2.zero;
if (textB != null) textB.anchoredPosition = new Vector2(0, slotHeight);
StartCoroutine(SlotMachineRoutine());
}
private IEnumerator SlotMachineRoutine()
{
while (true)
{
yield return new WaitForSeconds(switchInterval);
RectTransform current = isTextAOnTop ? textA : textB;
RectTransform next = isTextAOnTop ? textB : textA;
//두 텍스트를 동시에 슬라이드
Coroutine slideCurrent = StartCoroutine(Slide(current, new Vector2(0, -slotHeight), slideDuration));
Coroutine slideNext = StartCoroutine(Slide(next, Vector2.zero, slideDuration));
//둘 다 완료될 때까지 대기
yield return slideCurrent;
yield return slideNext;
//내려간 텍스트를 다시 위로 올리기
current.anchoredPosition = new Vector2(0, slotHeight);
//상태 전환
isTextAOnTop = !isTextAOnTop;
}
}
/// <summary>
/// RectTransform을 targetPos로 서서히 이동시키는 코루틴
/// </summary>
IEnumerator Slide(RectTransform rect, Vector2 targetPos, float duration)
{
Vector2 startPos = rect.anchoredPosition;
float elapsed = 0f;
while (elapsed < duration)
{
elapsed += Time.deltaTime;
float t = Mathf.Clamp01(elapsed / duration);
rect.anchoredPosition = Vector2.Lerp(startPos, targetPos, t);
yield return null;
}
rect.anchoredPosition = targetPos;
}
}
}
코드를 부모오브젝트에 삽입 후 News1, News2 할당
실행 화면
여기서 문제 :
text들이 슬라이드는 잘 되지만 저 안에서만 보여야 하는데 바깥의 움직이는 것까지 다 보인다!
간단하게 Rect Mask 2D 추가
더보기
✅ Rect Mask 2D란?
"자식 오브젝트들의 보이는 영역을 사각형(Rect) 안으로 제한"하는 컴포넌트.
쉽게 말하면,
Rect 영역 안에 있을 때만 보이고,
영역을 벗어나면 자동으로 잘려서 안 보임.
✅ Rect Mask 2D 특징
특징설명
성능 | 일반 Mask보다 훨씬 가볍다. (Shader 계산 안 하고, 단순 잘라내기만 함) |
사용 조건 | UI (Canvas 안) 에서만 사용 가능하다. |
적용 대상 | RectTransform을 가진 자식 오브젝트들 (텍스트, 이미지, 버튼 등) |
투명 처리 | 영역 바깥은 완전히 잘려서 아예 안 보인다 (반투명 같은 거 아님). |
한계 | 둥근 모양, 불규칙 마스크는 못 만든다. 오직 사각형만 잘라낸다. |
더보기
만약 Text가 여러개라면??
Text를 담을 List<>선언 -> 현재 보여줄 text를 currentIndex로 관리! (로직은 그대로)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SlotMachineText : MonoBehaviour
{
[Header("Text List")]
public List<RectTransform> textList = new List<RectTransform>();
[Header("Animation Settings")]
public float switchInterval = 2f;
public float slideDuration = 0.5f;
public float slotHeight = 100f;
private int currentIndex = 0; // 현재 중앙에 있는 텍스트 인덱스
private void Start()
{
// 초기 위치 세팅
for (int i = 0; i < textList.Count; i++)
{
if (i == 0)
textList[i].anchoredPosition = Vector2.zero; // 첫 번째 텍스트는 중앙
else
textList[i].anchoredPosition = new Vector2(0, slotHeight); // 나머지는 위에 숨겨놓기
}
StartCoroutine(SlotMachineRoutine());
}
IEnumerator SlotMachineRoutine()
{
while (true)
{
yield return new WaitForSeconds(switchInterval);
// current show text
RectTransform current = textList[currentIndex];
// next show text
int nextIndex = (currentIndex + 1) % textList.Count;
RectTransform next = textList[nextIndex];
//Both Slide Start
Coroutine slideCurrent = StartCoroutine(Slide(current, new Vector2(0, -slotHeight), slideDuration));
Coroutine slideNext = StartCoroutine(Slide(next, Vector2.zero, slideDuration));
//Wait until all Slides are finished
yield return slideCurrent;
yield return slideNext;
//Slide text under Update Up
current.anchoredPosition = new Vector2(0, slotHeight);
//Update Index
currentIndex = nextIndex;
}
}
IEnumerator Slide(RectTransform rect, Vector2 targetPos, float duration)
{
Vector2 startPos = rect.anchoredPosition;
float elapsed = 0f;
while (elapsed < duration)
{
elapsed += Time.deltaTime;
float t = Mathf.Clamp01(elapsed / duration);
rect.anchoredPosition = Vector2.Lerp(startPos, targetPos, t);
yield return null;
}
rect.anchoredPosition = targetPos;
}
}
'Unity' 카테고리의 다른 글
모바일 앱/게임 제작 시 필요한 Unity 권한 선언 종류 (0) | 2025.05.28 |
---|---|
Unity 로딩씬 구현하기 (0) | 2025.04.14 |
Unity 출석체크 시스템 구현하기 (2) | 2025.04.08 |
Unity 푸시 알람 기능 구현 (0) | 2025.03.31 |
오클루전 컬링 (0) | 2024.10.26 |