✅ 기능
프로그램에서 사용자에게 동영상 파일을 재생하기 위해서는 동영상 파일을 프로그램 내에 포함할 수 있습니다. 하지만 프로그램 특성 상 수많은 동영상이 필요로 할경우, 모든 동영상을 프로그램에 포함하여 제공하면 용량이 불필요하게 커질 수 있는 문제점이 있습니다. 이런 문제를 개선하고자 로컬에 동영상 파일을 포함하여 제공하지 않고, URL을 이용하여 스트림으로 받은 비디오를 재생하고, 비디오 재생 및 중지를 자연스럽게 관리해주는 스크립트를 작성하였습니다.
🛑 기능 요구사항
[필수] 비디오 파일(.mp4 등)을 다운로드 받을 수 있는 다이렉트 URL이 있어야합니다. (FTP 스트리밍 등)
✅ 흐름도
✅ 사용 예시
✅ 구현
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//비디오 컴포넌트를 사용하기위해 임포트
using UnityEngine.Video;
public class VideoController : MonoBehaviour
{
private VideoPlayer mTargetVideoPlayer; //비디오 플레이어
[Header("비디오의 오디오 출력 소스(없을경우 None)")]
[SerializeField] private AudioSource mTargetAudioSource; //오디오소스
[Header("전환시 사운드 딜레이 시간")]
[SerializeField] private float mSoundLerpDuration = 1.0f; //전환 시간
[Header("플레이어를 감지하여 활성/비활성 전환시 전환되는 시간")]
[SerializeField] private float mVideoLerpDuration = 1.0f; //전환 시간
/// <summary>
/// 미리 설정된 재생속도
/// </summary>
private float mOriginPlaybackSpeed;
/// <summary>
/// 미리 설정된 오디오 불륨
/// </summary>
private float mOriginAudioVolume;
private Coroutine mVideoLerpCoroutine, mSoundLerpCoroutine; //코루틴
private void Awake()
{
//부모에게서 비디오 플레이어 컴포넌틑 가져오기
mTargetVideoPlayer = transform.parent.GetComponent<VideoPlayer>();
if (mTargetVideoPlayer == null) { Debug.LogErrorFormat("{0}에서 비디오 플레이어를 찾을 수 없음!", name); }
}
private void Start()
{
//비디오의 초기 재생속도를 저장 후 재생중지
mOriginPlaybackSpeed = mTargetVideoPlayer.playbackSpeed;
mTargetVideoPlayer.playbackSpeed = 0f;
//오디오 소스가 존재하는경우 불룸 저장
if(mTargetAudioSource != null) { mOriginAudioVolume = mTargetAudioSource.volume; }
//트리거를 보기위한 디버그 큐브 제거
Destroy(GetComponent<MeshFilter>());
Destroy(GetComponent<MeshRenderer>());
}
private void OnTriggerEnter(Collider other) //무언가가 비디오 영역에 진입
{
if (other.tag == "Player")
{
if (other.GetComponent<PlayerController>().IsMine)
{
if (mVideoLerpCoroutine != null) { StopCoroutine(mVideoLerpCoroutine); }
mVideoLerpCoroutine = StartCoroutine(COR_ToggleVideoLerp(true));
}
}
}
private void OnTriggerExit(Collider other) //무언가가 비디오 영역에서 퇴장
{
if (other.tag == "Player")
{
if (other.GetComponent<PlayerController>().IsMine)
{
if (mVideoLerpCoroutine != null) { StopCoroutine(mVideoLerpCoroutine); }
mVideoLerpCoroutine = StartCoroutine(COR_ToggleVideoLerp(false));
}
}
}
private IEnumerator COR_ToggleSoundLerp(bool isEnable)
{
float process = 0f;
float currentAudioVolume = mTargetAudioSource.volume;
while (process < 1.0f)
{
//process 진행도 갱신
process += Time.deltaTime / mSoundLerpDuration;
//volume을 서서히 증가 또는 감소
mTargetAudioSource.volume = Mathf.Lerp(currentAudioVolume, isEnable ? mOriginPlaybackSpeed : 0f, process);
yield return null;
}
}
/// <summary>
/// 보간을 사용하여 서서히 비디오를 멈추거나, 재생한다.
/// </summary>
/// <param name="isEnable"></param>
/// <returns></returns>
private IEnumerator COR_ToggleVideoLerp(bool isEnable)
{
//비활성화로 전환 및 오디오소스가 활성화라면 사운드 비활성화
if(!isEnable && mTargetAudioSource != null)
{
if(mSoundLerpCoroutine != null) { StopCoroutine(mSoundLerpCoroutine); }
yield return mSoundLerpCoroutine = StartCoroutine(COR_ToggleSoundLerp(isEnable));
}
//진행도는 0으로
float process = 0f;
float currentPlaybackSpeed = mTargetVideoPlayer.playbackSpeed;
while (process < 1.0f)
{
//process 진행도 갱신
process += Time.deltaTime / mVideoLerpDuration;
//playbackSpeed를 서서히 증가 또는 감소
mTargetVideoPlayer.playbackSpeed = Mathf.Lerp(currentPlaybackSpeed, isEnable ? mOriginPlaybackSpeed : 0f, process);
yield return null;
}
//활성화로 전환 및 오디오소스가 활성화라면 사운드
if(isEnable && mTargetAudioSource != null)
{
if(mSoundLerpCoroutine != null) { StopCoroutine(mSoundLerpCoroutine); }
yield return mSoundLerpCoroutine = StartCoroutine(COR_ToggleSoundLerp(isEnable));
}
}
}
private VideoPlayer mTargetVideoPlayer; //비디오 플레이어
[SerializeField] private AudioSource mTargetAudioSource; //오디오소스
- 비디오 플레이어와 오디오소스를 사용합니다.
- 비디오의 재생속도와, 오디오소스의 불륨을 서서히 증가, 감소시키면서 관리합니다.
private void Awake()
- Awake에서는 부모 게임오브젝트에서 비디오플레이어를 가져옵니다.
- 만약 비디오 플레이어가 없다면, 이것은 오류이기에 오류디버그를 출력합니다.
private void Start()
- Start에서는 초기속성을 저장하고, 디버그를 위해 만들었던 디버그 큐브를 제거합니다.
private void OnTriggerEnter(Collider other) //무언가가 비디오 영역에 진입
private void OnTriggerExit(Collider other) //무언가가 비디오 영역에서 퇴장
- 트리거를 이용하여 플레이어가 영역내로 진입하는지, 영역에서 퇴장하는지 확인합니다.
- 코루틴을 호출하여 진입시 TRUE, 퇴장시 FALSE를 인자로 건네줍니다.
private IEnumerator COR_ToggleSoundLerp(bool isEnable)
- 사운드를 서서히 조절하는 코루틴입니다.
- 비활성화 조건에서 VideoLerp보다 먼저 실행되며, 사운드를 없앤 후 비디오를 멈추도록 합니다.
- 이유는, 사운드가 있는 상태에서 비디오를 천천히 멈추게되면, 사운드도 느려지면서 출력이 되기 때문입니다.
private IEnumerator COR_ToggleVideoLerp(bool isEnable)
- 비디오 재생속도를 서서히 조절하는 코루틴입니다.
- 비디오 playbackSpeed를 변경시키며, 활성화 조건에서 비디오 프로세스가 끝나면 사운드를 변경하도록 합니다.
✅ 사용
- 구조는 다음과 같습니다.
- VideoPlayer 컴포넌트가 들어가는 오브젝트에는 URL을 설정합니다.
- 해당 URL은 .mp4파일과 같은 파일을 다운로드 받는 경로여야합니다.
- 렌더텍스쳐를 이용하여 렌더를 준비하고, 필요시 오디오소스도 넣어줍니다.
- 두번째 게임오브젝트인 VideoController에는 작성한 스크립트를 컴포넌트로 포함시킵니다.
- 트리거를 사용하기에 박스콜라이더 등 콜라이더를 사용한 후 Trigger을 켜줍니다.
- 오디오 소스를 사용하는경우 인스펙터에서 등록시키고, 딜레이시간도 지정해줍니다.
- 마지막으로 Screen은 렌더텍스쳐 파일을 출력으로하는 머터리얼을 사용합니다.
- 필요시 오디오소스를 포함시키고, 거리 및 불륨을 설정합니다.
'unity game modules' 카테고리의 다른 글
[유니티] 인벤토리 시스템(번외) - 아이템 툴팁 (0) | 2023.02.06 |
---|---|
[유니티] 레터박스(Lettering Box) 구현하기 (0) | 2023.01.06 |
[유니티] 인벤토리 시스템(번외) - 쿨타임 기능 (0) | 2022.12.28 |
[유니티] 인벤토리 시스템(6) - 아이템 사용 (0) | 2022.12.27 |
[유니티] 인벤토리 시스템(5) - 아이템 슬롯 관리 (0) | 2022.12.26 |