✅  기능

특정한 스토리나 전달하고자 할 메시지를 강조하기위해서, 마치 영상을 보고있는 느낌을 주기위해 레터박스를 사용할 수 있습니다. 레터박스 기능을 구현하고, 매우 쉽게 호출하여 연출할 수 있도록 정리해봤습니다.

 

✅  응용 기능

UI에서 사용하는 RectTransform을 이용합니다.

 

Unity - Scripting API: RectTransform

RectTransforms are used for GUI but can also be used for other things. It's used to store and manipulate the position, size, and anchoring of a rectangle and supports various forms of scaling based on a parent RectTransform. Note: The Inspector changes whi

docs.unity3d.com

 

✅  흐름도

매우 단순한 흐름이다

 

✅ 사용 예시

 

 

✅ 구현

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 레터박스 기능을 제공하는 클래스
/// </summary>
public class LetteringBoxController : Singleton<LetteringBoxController>
{
    private static bool mIsEnable; //현재 활성화 되어있는가?

    /// <summary>
    /// 현재 레터박스가 활성화 되어있는가?
    /// </summary>
    public static bool IsEnable
    {
        get
        {
            return mIsEnable;
        }
    }

    [Header("위쪽 레터박스 트랜스폼")]
    [SerializeField] private RectTransform mTopBoxTransform;

    [Header("아래쪽 레터박스 트랜스폼")]
    [SerializeField] private RectTransform mBottomBoxTransform;

    [Header("레터박스 활성화 시 설정할 높이(Scale With Screen Size 800*600 기준)")]
    [SerializeField][Range(0f, 300f)] private float mBoxHeight = 50f; //활성화 시 사용할 박스의 높이

    [Header("레터박스를 토글할 때 활성화/비활성화 할 UI요소들")]
    [SerializeField] private CanvasGroup[] mToggleObjects;

    private Vector2 mEnableBoxSize; //활성화 시 사용할 박스의 크기
    private Coroutine mToggleCoroutine; //토글에 사용할 코루틴

    private void Awake()
    {
        //초기 사이즈는 0으로 설정
        mBottomBoxTransform.sizeDelta = mTopBoxTransform.sizeDelta = Vector2.zero;

        //박스 높이 저장
        mEnableBoxSize = new Vector2(0f, mBoxHeight);
    }

    /// <summary>
    /// 레터박스와 UI요소를 토글한다.
    /// </summary>
    /// <param name="isEnable">레터박스를 활성화 할것인가?</param>
    /// <param name="delayTime">레터박스 토글을 시작할 딜레이 시간</param>
    /// <param name="duration">레터박스 토글에 걸리는 소요시간</param>
    public void ToggleBox(bool isEnable, float delayTime = 0f, float duration = 1.0f)
    {
        if(mToggleCoroutine != null) { StopCoroutine(mToggleCoroutine); }
        mToggleCoroutine = StartCoroutine(COR_ToggleLetteringBox(isEnable, delayTime, duration));
    }

    /// <summary>
    /// 레터박스와 UI요소를 토글한다.
    /// </summary>
    private IEnumerator COR_ToggleLetteringBox(bool isEnable, float delayTime, float duration)
    {
        //딜레이가 있다면 대기
        if(delayTime > 0f) { yield return new WaitForSeconds(delayTime); }

        float process = 0f; //프로세스 생성
        Vector2 currentSize = mTopBoxTransform.sizeDelta; //현재 사이즈 가져오기

        if(isEnable) { mIsEnable = true; } //활성화 상태 등록

        while(process < 1.0f)
        {
            //duration을 적용하여 process 증가
            process += Time.deltaTime / duration;

            //레터박스 크기 설정
            mTopBoxTransform.sizeDelta = mBottomBoxTransform.sizeDelta = Vector2.Lerp(currentSize, isEnable ? mEnableBoxSize : Vector2.zero, process);

            //캔버스 그룹 토글
            foreach(CanvasGroup canvasGroup in mToggleObjects) { canvasGroup.alpha = Mathf.Lerp(canvasGroup.alpha, isEnable ? 0f : 1f, process); }

            yield return null;
        }

        if(!isEnable) { mIsEnable = false; } //비활성화 상태 등록
    }
}
  • 레터박스는 씬 내에 하나만 존재하며, 컨트롤러(본 스크립트)또한 하나만 존재합니다.
  • 싱글턴 패턴을 적용하여 외부에서 간편하게 호출하도록 구현하였습니다.

 

public static bool IsEnable
  • 현재 레터박스가 활성화 되어있는지 확인하기 위한 정적변수입니다.
  • LetteringBoxController.IsEnable로 외부에서 현재 레터박스가 활성화되었는지 검사할 수 있습니다.

 

[Header("위쪽 레터박스 트랜스폼")]
[SerializeField] private RectTransform mTopBoxTransform;

[Header("아래쪽 레터박스 트랜스폼")]
[SerializeField] private RectTransform mBottomBoxTransform;
  • 캔버스에서 위쪽, 아래쪽에 있는 레터박스 오브젝트의 트랜스폼입니다.
  • 상단 레터박스라고 가정했을때, 아래 사진과 같이 앵커는 상단 및 스트레치, 피벗은 상단 중앙으로 설정합니다.

 

[Header("레터박스 활성화 시 설정할 높이(Scale With Screen Size 800*600 기준)")]
[SerializeField][Range(0f, 300f)] private float mBoxHeight = 50f; //활성화 시 사용할 박스의 높이
  • 레터박스를 활성화 할 때 레터박스의 높이를 설정합니다.
  • 사용하는 높이는 캔버스 설정이 Scale With Screen Size로 되어있음을 기준으로 하며, 높이는 600으로 설정한 상태입니다.

 

[Header("레터박스를 토글할 때 활성화/비활성화 할 UI요소들")]
[SerializeField] private CanvasGroup[] mToggleObjects;
  • 레터박스가 토글될 때 함께 토글될 게임오브젝트들을 설정하는 배열입니다.
  • 레터박스가 활성화되면 배열에 있는 오브젝트들의 캔버스그룹을 사용하여 서서히 투명해지게 합니다.

 

public void ToggleBox(bool isEnable, float delayTime = 0f, float duration = 1.0f)
  • 외부에서 호출하며, 레터박스를 토글하는 함수입니다.
isEnable: 레터박스를 활성화 할것인가?
delayTime: 레터박스 토글을 시작할 딜레이 시간
duration: 레터박스 토글에 걸리는 소요시간

 

private IEnumerator COR_ToggleLetteringBox(bool isEnable, float delayTime, float duration)
  • 실질적인 토글 수행하는 코루틴으로, 서서히 나타나고, 사라지게 하도록 합니다.
  • process를 사용하여 duration과 함께 계산하여 duration을 설정한 값대로 정확히 작동하게 합니다.

 

✅ 사용(외부에서 호출)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GlobalEventHandler : Singleton<GlobalEventHandler>
{
    ...

    /// <summary>
    /// 특정 Id의 이벤트를 시작한다
    /// </summary>
    /// <param name="eventId">시작할 이벤트 Id</param>
    public void RunEvent(int eventId)
    {
        ...
        
        switch (mCurrentEventId)
        {
            case 0: //게임시작
                {
                    //레터박스 활성화
                    LetteringBoxController.Instance.ToggleBox(true);

                    //대사 호출
                    float duration = QuoteManager.Instance.DisplayQuote(QuoteManager.Instance.GetPreloadLabel("Player"), 0);

                    //이벤트 호출
                    RunEvent(1, duration);
                    break;
                }

            case 1: //움직임 튜토리얼
                {
                    //대사 호출
                    float duration = QuoteManager.Instance.DisplayQuote(QuoteManager.Instance.GetPreloadLabel("Tutorial0"), 1, null, 0f);

                    //레터박스 활성화
                    LetteringBoxController.Instance.ToggleBox(false, duration);

                    break;
                }

			...          
            
        }
    }

    ...
    
}

 

LetteringBoxController.Instance.ToggleBox(true);
LetteringBoxController.Instance.ToggleBox(false, duration);
  • 인자에 true가 들어가면 레터박스가 활성화됩니다.
  • 두번째 인자인 duration은 duration초 만큼 기다렸다가 토글되게 합니다.
bonnate