191 lines
6.3 KiB
C#
191 lines
6.3 KiB
C#
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using UnityEngine.Serialization;
|
||
using UnityEngine.Video;
|
||
|
||
public class VideoUtility : MonoBehaviour
|
||
{
|
||
[SerializeField, FormerlySerializedAs("player")] private VideoPlayer _primaryPlayer;
|
||
[SerializeField] private VideoPlayer _secondaryPlayer;
|
||
[SerializeField, FormerlySerializedAs("audioSource")] private AudioSource _audioSource;
|
||
[SerializeField, FormerlySerializedAs("fon")] private VideoClip _menuBackground;
|
||
[SerializeField] private List<VideoClip> _characterBackgrounds;
|
||
[SerializeField, FormerlySerializedAs("ads")] private VideoClip _ads;
|
||
[SerializeField, FormerlySerializedAs("ending")] private VideoClip _ending;
|
||
[SerializeField] private float _crossFadeDuration = 1f;
|
||
[SerializeField, FormerlySerializedAs("canvas")] private Canvas _canvas;
|
||
|
||
private static VideoUtility _instance;
|
||
private VideoPlayer _activeBackgroundPlayer;
|
||
private Coroutine _crossFadeCoroutine;
|
||
|
||
public static float AdsLength => (float)_instance._ads.length;
|
||
public static float VictoryLength => (float)_instance._ending.length;
|
||
|
||
private void Update()
|
||
{
|
||
if (Input.GetKeyDown(KeyCode.Alpha5))
|
||
PlayFon();
|
||
|
||
if (Input.GetKeyDown(KeyCode.Alpha6))
|
||
PlayAds();
|
||
|
||
if (Input.GetKeyDown(KeyCode.Alpha7))
|
||
PlayEnding();
|
||
}
|
||
|
||
public void Initialize()
|
||
{
|
||
if (_instance == null)
|
||
_instance = this;
|
||
|
||
ConfigureBackgroundPlayer(_primaryPlayer);
|
||
ConfigureBackgroundPlayer(_secondaryPlayer);
|
||
_activeBackgroundPlayer = _primaryPlayer;
|
||
PlayBackgroundImmediately(_menuBackground);
|
||
}
|
||
|
||
public static void CrossFadeToCharacter(int characterIndex)
|
||
{
|
||
if (characterIndex < 0 || characterIndex >= _instance._characterBackgrounds.Count)
|
||
{
|
||
Debug.LogError($"Не найден видеофон для персонажа с индексом {characterIndex}");
|
||
return;
|
||
}
|
||
|
||
_instance.StartCrossFade(_instance._characterBackgrounds[characterIndex]);
|
||
}
|
||
|
||
public static void CrossFadeToMenu()
|
||
=> _instance.StartCrossFade(_instance._menuBackground);
|
||
|
||
public static void PlayFon()
|
||
=> CrossFadeToMenu();
|
||
|
||
public static void PlayAds()
|
||
=> _instance.PlayForeground(_instance._ads);
|
||
|
||
public static void PlayEnding()
|
||
=> _instance.PlayForeground(_instance._ending);
|
||
|
||
private void StartCrossFade(VideoClip targetClip)
|
||
{
|
||
if (targetClip == null)
|
||
{
|
||
Debug.LogError("Не назначен видеофон для переключения");
|
||
return;
|
||
}
|
||
|
||
NormalizeInterruptedCrossFade();
|
||
|
||
if (_activeBackgroundPlayer.clip == targetClip && _activeBackgroundPlayer.isPlaying)
|
||
return;
|
||
|
||
_crossFadeCoroutine = StartCoroutine(CrossFadeCoroutine(targetClip));
|
||
}
|
||
|
||
private IEnumerator CrossFadeCoroutine(VideoClip targetClip)
|
||
{
|
||
VideoPlayer outgoingPlayer = _activeBackgroundPlayer;
|
||
VideoPlayer incomingPlayer = GetInactivePlayer();
|
||
|
||
ConfigureBackgroundPlayer(incomingPlayer);
|
||
incomingPlayer.Stop();
|
||
incomingPlayer.clip = targetClip;
|
||
incomingPlayer.targetCameraAlpha = 0f;
|
||
incomingPlayer.Prepare();
|
||
|
||
//while (incomingPlayer.isPrepared == false)
|
||
// yield return null;
|
||
|
||
incomingPlayer.Play();
|
||
|
||
float elapsedTime = 0f;
|
||
float duration = Mathf.Max(_crossFadeDuration, 0.01f);
|
||
|
||
while (elapsedTime < duration)
|
||
{
|
||
elapsedTime += Time.unscaledDeltaTime;
|
||
float progress = Mathf.Clamp01(elapsedTime / duration);
|
||
incomingPlayer.targetCameraAlpha = progress;
|
||
outgoingPlayer.targetCameraAlpha = 1f - progress;
|
||
yield return null;
|
||
}
|
||
|
||
incomingPlayer.targetCameraAlpha = 1f;
|
||
outgoingPlayer.targetCameraAlpha = 0f;
|
||
outgoingPlayer.Stop();
|
||
_activeBackgroundPlayer = incomingPlayer;
|
||
_crossFadeCoroutine = null;
|
||
}
|
||
|
||
private void NormalizeInterruptedCrossFade()
|
||
{
|
||
if (_crossFadeCoroutine == null)
|
||
return;
|
||
|
||
StopCoroutine(_crossFadeCoroutine);
|
||
_crossFadeCoroutine = null;
|
||
|
||
_activeBackgroundPlayer = _primaryPlayer.targetCameraAlpha >= _secondaryPlayer.targetCameraAlpha
|
||
? _primaryPlayer
|
||
: _secondaryPlayer;
|
||
|
||
VideoPlayer inactivePlayer = GetInactivePlayer();
|
||
_activeBackgroundPlayer.targetCameraAlpha = 1f;
|
||
inactivePlayer.targetCameraAlpha = 0f;
|
||
inactivePlayer.Stop();
|
||
}
|
||
|
||
private VideoPlayer GetInactivePlayer()
|
||
=> _activeBackgroundPlayer == _primaryPlayer ? _secondaryPlayer : _primaryPlayer;
|
||
|
||
private void PlayBackgroundImmediately(VideoClip clip)
|
||
{
|
||
_secondaryPlayer.Stop();
|
||
_secondaryPlayer.targetCameraAlpha = 0f;
|
||
_activeBackgroundPlayer.Stop();
|
||
_activeBackgroundPlayer.clip = clip;
|
||
_activeBackgroundPlayer.targetCameraAlpha = 1f;
|
||
_activeBackgroundPlayer.Play();
|
||
}
|
||
|
||
private void ConfigureBackgroundPlayer(VideoPlayer videoPlayer)
|
||
{
|
||
videoPlayer.renderMode = VideoRenderMode.CameraFarPlane;
|
||
videoPlayer.targetCamera = _primaryPlayer.targetCamera;
|
||
videoPlayer.aspectRatio = _primaryPlayer.aspectRatio;
|
||
videoPlayer.isLooping = true;
|
||
videoPlayer.playOnAwake = false;
|
||
videoPlayer.audioOutputMode = VideoAudioOutputMode.None;
|
||
}
|
||
|
||
private void PlayForeground(VideoClip clip)
|
||
{
|
||
NormalizeInterruptedCrossFade();
|
||
_primaryPlayer.Stop();
|
||
_secondaryPlayer.Stop();
|
||
_primaryPlayer.renderMode = VideoRenderMode.CameraNearPlane;
|
||
_primaryPlayer.targetCameraAlpha = 1f;
|
||
_primaryPlayer.isLooping = false;
|
||
_primaryPlayer.clip = clip;
|
||
_primaryPlayer.audioOutputMode = VideoAudioOutputMode.AudioSource;
|
||
_primaryPlayer.EnableAudioTrack(0, true);
|
||
_primaryPlayer.SetTargetAudioSource(0, _audioSource);
|
||
_audioSource.Stop();
|
||
StartCoroutine(PrepareAndPlayForeground());
|
||
}
|
||
|
||
private IEnumerator PrepareAndPlayForeground()
|
||
{
|
||
_primaryPlayer.Prepare();
|
||
|
||
while (_primaryPlayer.isPrepared == false)
|
||
yield return null;
|
||
|
||
_audioSource.Play();
|
||
_primaryPlayer.Play();
|
||
}
|
||
}
|