Files

689 lines
22 KiB
C#
Raw Permalink Normal View History

2025-01-25 04:38:09 +08:00
using System.Collections;
using System.Collections.Generic;
using System.IO;
using Thousandto.Launcher.ExternalLibs;
using UnityEngine;
using UnityEngine.Video;
using AppManager = UnityEngine.Gonbest.MagicCube.AppManager;
#if FUNCELL_LAUNCHER
using MyRuntimePlatform = Thousandto.Launcher.Logic.MyRuntimePlatform;
using LauncherManager = Thousandto.Launcher.Logic.LauncherManager;
#endif
public class VideoRootScript : MonoBehaviour
{
#region//组件
private Camera _camera = null;
private Transform _mask = null;
private VideoPlayer _videoPlayer = null;
private AudioSource _audioSource = null;
#endregion
#region//私有变量
private bool _isInit = false;
private string _url = "http//xxxxxxxxxxxxxx";
private string _fileName = string.Empty;
private string _ext = "mp4";
private OnPreparedCall _preparedCallBack = null;
private OnFinishCall _finishCallBack = null;
private List<string> _fileNames = new List<string>();
//texture缓存
private Dictionary<string, Texture> _texCache = new Dictionary<string, Texture>();
#endregion
#region//const
private const int TEXTURE_COUNT = 4;
private const string TEX_MASK_0 = "tex_logininback_3";
private const string TEX_MASK_1 = "tex_logininback";
private const string TEX_MASK_2 = "tex_logininback_1";
private const string TEX_MASK_3 = "tex_logininback_2";
#endregion
#region//delegate
//视频准备完成回调
public delegate void OnPreparedCall();
//视频播放完毕回调
public delegate void OnFinishCall();
#endregion
#region//私有函数
private void Initialize()
{
if (!_isInit)
{
if (_camera == null)
_camera = transform.Find("Camera_Video").GetComponent<Camera>();
_mask = transform.Find("Camera_Video/Mask");
_videoPlayer = RequireComponent<VideoPlayer>(_camera.gameObject);
_audioSource = RequireComponent<AudioSource>(_camera.gameObject);
_videoPlayer.playOnAwake = false;
_videoPlayer.errorReceived += PlayErrorRecived;
_videoPlayer.aspectRatio = VideoAspectRatio.Stretch;
_audioSource.playOnAwake = false;
_mask.gameObject.SetActive(false);
Renderer rd = _mask.GetComponent<Renderer>();
if (rd != null)
{
rd.sharedMaterial = null;
}
_videoPlayer.source = VideoSource.Url;
_isInit = true;
}
}
private void UnInitialize()
{
_videoPlayer.errorReceived -= PlayErrorRecived;
_videoPlayer = null;
Destroy(_camera.GetComponent<VideoPlayer>());
_isInit = false;
}
//判断文件是否在apk中
private bool IsFileInApk(string relationPath)
{
return AppManager.Instance.AssetInApp(relationPath);
}
private T RequireComponent<T>(GameObject go) where T : Component
{
if (go == null)
return default(T);
T t = go.GetComponent<T>();
if (t == null)
{
t = go.AddComponent<T>();
}
return t;
}
#endregion
#region //静态函数
//准备视频
public static void PreVideo(string name, OnPreparedCall preparedCallBack = null, OnFinishCall finishCall = null, bool isShowMask = false, bool isLoop = false, VideoPlayExt extType = VideoPlayExt.Mp4)
{
var videoRoot = GameObject.Find("[VideoRoot]");
VideoRootScript videoScript = null;
if (!videoRoot)
{
var asset = Resources.Load("Default/System/VideoRoot");
videoRoot = GameObject.Instantiate(asset) as GameObject;
videoRoot.name = "[VideoRoot]";
if (videoRoot != null)
{
GameObject.DontDestroyOnLoad(videoRoot);
}
}
videoScript = videoRoot.GetComponent<VideoRootScript>();
if (videoScript == null)
{
videoRoot.AddComponent<VideoRootScript>();
}
videoScript.PrepareVideo("video_login", preparedCallBack, finishCall, isShowMask, isLoop, extType);
}
public static void PlayVideo(string name, OnPreparedCall preparedCallBack = null, OnFinishCall finishCall = null, bool isShowMask = false, bool isLoop = false, VideoPlayExt extType = VideoPlayExt.Mp4)
{
var videoRoot = GameObject.Find("[VideoRoot]");
VideoRootScript videoScript = null;
if (!videoRoot)
{
var asset = Resources.Load("Default/System/VideoRoot");
videoRoot = GameObject.Instantiate(asset) as GameObject;
videoRoot.name = "[VideoRoot]";
if (videoRoot != null)
{
GameObject.DontDestroyOnLoad(videoRoot);
}
}
videoScript = videoRoot.GetComponent<VideoRootScript>();
if (videoScript == null)
{
videoRoot.AddComponent<VideoRootScript>();
}
videoScript.Play("video_login", preparedCallBack, finishCall, isShowMask, isLoop, extType);
}
#endregion
#region//公共函数
/// <summary>
/// 准备视频
/// </summary>
/// <param name="name"></param>
/// <param name="preparedCallBack"></param>
/// <param name="finishCall"></param>
/// <param name="isShowMask"></param>
/// <param name="isLoop"></param>
/// <param name="extType"></param>
public void PrepareVideo(string name, OnPreparedCall preparedCallBack = null, OnFinishCall finishCall = null, bool isShowMask = false, bool isLoop = false, VideoPlayExt extType = VideoPlayExt.Mp4)
{
if (string.IsNullOrEmpty(name))
return;
_fileName = name;
_preparedCallBack = preparedCallBack;
_finishCallBack = finishCall;
Initialize();
if (isShowMask)
{
ShowMaskTexture();
}
else
{
_mask.gameObject.SetActive(false);
}
_videoPlayer.isLooping = isLoop;
SetExtName(extType);
Prepare(name);
}
/// <summary>
///
/// </summary>
/// <param name="name">视频名字</param>
/// <param name="type">播放类型</param>
/// <param name="extType">视频格式</param>
/// <param name="preparedCallBack">视频准备成功回调</param>
/// <param name="finishCall">视频播放完毕成功回调</param>
/// <param name="isShowMask">是否显示背景遮罩</param>
public void Play(string name, OnPreparedCall preparedCallBack = null, OnFinishCall finishCall = null, bool isShowMask = false, bool isLoop = false, VideoPlayExt extType = VideoPlayExt.Mp4)
{
if (string.IsNullOrEmpty(name))
return;
_fileName = name;
_preparedCallBack = preparedCallBack;
_finishCallBack = finishCall;
Initialize();
if (isShowMask)
{
ShowMaskTexture();
}
else
{
_mask.gameObject.SetActive(false);
}
_mask.gameObject.SetActive(false);
_videoPlayer.isLooping = isLoop;
SetExtName(extType);
PlayLocal(name);
}
public void StopVideo()
{
if (_videoPlayer != null)
{
_videoPlayer.Stop();
//隐藏视频播放节点
_preparedCallBack = null;
_finishCallBack = null;
UnInitialize();
gameObject.SetActive(false);
}
}
public bool IsPlaying()
{
if (_videoPlayer != null)
{
return _videoPlayer.isPlaying;
}
return false;
}
//点击跳过
public void Skip()
{
//停止视频播放
if (_videoPlayer != null)
{
_videoPlayer.Stop();
}
//隐藏视频播放节点
_preparedCallBack = null;
_finishCallBack = null;
gameObject.SetActive(false);
}
#endregion
#region//私有函数
//播放在线视频
private void PlayOline(string name)
{
string url = FixOnlineUrl(name);
if (string.IsNullOrEmpty(url))
{
return;
}
StartCoroutine(playVideo(url));
}
//播放本地视频
private void PlayLocal(string name)
{
string path = IsExitVideoFile(name);
if (string.IsNullOrEmpty(path))
{
//本地视频不存在 播放online视频
PlayOline(name);
}
else
{
string url = FixLocalUrl(path);
if (!gameObject.activeSelf)
gameObject.SetActive(true);
StartCoroutine(playVideo(url));
}
}
private void Prepare(string name)
{
string url = string.Empty;
string path = IsExitVideoFile(name);
if (string.IsNullOrEmpty(path))
{
//本地视频不存在
url = FixOnlineUrl(name);
if (string.IsNullOrEmpty(url))
{
return;
}
}
else
{
url = FixLocalUrl(path);
if (!gameObject.activeSelf)
gameObject.SetActive(true);
}
StartCoroutine(PrepareVideo(url));
}
//判断视频文件是否存在
private string IsExitVideoFile(string name)
{
string ret = string.Empty;
string streamingPath = string.Empty;
#if FUNCELL_LAUNCHER
//获取当前平台
MyRuntimePlatform runtimePlatform = LauncherManager.Instance.Data.RuntimePlatform;
switch (runtimePlatform)
{
case MyRuntimePlatform.Standalone:
case MyRuntimePlatform.AndroidEditor:
case MyRuntimePlatform.IOSEditor:
case MyRuntimePlatform.StandaloneEditor:
streamingPath = Application.streamingAssetsPath;
ret = string.Format("{0}/Assets/GameAssets/Resources/Video/{1}{2}", streamingPath, name, _ext);
if (!System.IO.File.Exists(ret))
{
ret = string.Empty;
}
return ret;
case MyRuntimePlatform.IOS:
case MyRuntimePlatform.Android:
streamingPath = string.Format("{0}/StreamingAssets", Application.persistentDataPath);
ret = string.Format("{0}/Assets/GameAssets/Resources/Video/{1}{2}", streamingPath, name, _ext);
if (!System.IO.File.Exists(ret))
{
ret = string.Empty;
}
if (string.IsNullOrEmpty(ret))
{
//从apk中查找是否存在该文件
string relationPath = string.Format("Assets/GameAssets/Resources/Video/{0}{1}", name, _ext);
if (IsFileInApk(relationPath))
{
streamingPath = Application.streamingAssetsPath;
ret = string.Format("{0}/Assets/GameAssets/Resources/Video/{1}{2}", streamingPath, name, _ext);
}
}
break;
default:
break;
}
#else
streamingPath = Application.dataPath;
ret = string.Format("{0}/GameAssets/Resources/Video/{1}{2}", streamingPath, name, _ext);
if (!System.IO.File.Exists(ret))
{
ret = string.Empty;
}
#endif
return ret;
}
private string FixOnlineUrl(string name)
{
string ret = string.Format("{0}/{1}", _url, name);
return ret;
}
private string FixLocalUrl(string path)
{
////判断视频本地文件是否存在
return path.Replace(@"\", "/");
}
private string FixTexturePath(string name)
{
//string lan =UnityEngine.Gonbest.MagicCube.FLanguage.Default;
string ret = string.Format("GameAssets/Resources/Texture/UI/CH/{0}", name);
return ret;
}
//private void OnGUI()
//{
// GUIStyle style = new GUIStyle
// {
// border = new RectOffset(10, 10, 10, 10),
// fontSize = 25,
// fontStyle = FontStyle.BoldAndItalic,
// };
// // normal:Rendering settings for when the component is displayed normally.
// style.normal.textColor = new Color(200 / 255f, 180 / 255f, 150 / 255f); // 需要除以255因为范围是0-1
// //GUI.Label(new Rect(100, 100, 200, 80), , style);
//}
private void SetExtName(VideoPlayExt extType)
{
switch (extType)
{
case VideoPlayExt.Mov:
_ext = ".mov";
break;
case VideoPlayExt.Mpg:
_ext = ".mpg";
break;
case VideoPlayExt.Mpeg:
_ext = ".mpeg";
break;
case VideoPlayExt.Mp4:
_ext = ".mp4";
break;
case VideoPlayExt.Avi:
_ext = ".avi";
break;
case VideoPlayExt.Asf:
_ext = ".asf";
break;
}
}
//播放错误回调
private void PlayErrorRecived(VideoPlayer vp, string msg)
{
if (!string.IsNullOrEmpty(msg))
{
UnityEngine.Debug.LogError("播放错误播放错误播放错误播放错误播放错误播放错误播放错误");
if (_preparedCallBack != null)
{
_preparedCallBack();
_preparedCallBack = null;
}
if (_finishCallBack != null)
{
_finishCallBack();
_finishCallBack = null;
}
}
}
//准备视频
private IEnumerator PrepareVideo(string url)
{
_videoPlayer.url = url;
_videoPlayer.renderMode = VideoRenderMode.CameraFarPlane;
_videoPlayer.audioOutputMode = VideoAudioOutputMode.AudioSource;
_videoPlayer.controlledAudioTrackCount = 1;
_videoPlayer.SetTargetAudioSource(0, _audioSource);
//这里一定要让以上工作完成后才能开始准备videoPlayer
_videoPlayer.Prepare();
while (!_videoPlayer.isPrepared)
{
//Debug.Log("Preparing Video");
yield return null;
}
if (_preparedCallBack != null)
{
_preparedCallBack();
_preparedCallBack = null;
gameObject.SetActive(false);
}
}
private IEnumerator playVideo(string url)
{
if (string.Equals(_videoPlayer.url, url))
{
//判断视频是否准备好了
if (_videoPlayer.isPrepared)
{
_videoPlayer.Play();
_audioSource.enabled = true;
//视频播放成功了隐藏mask
//_mask.gameObject.SetActive(false);
yield return null;
//等待一帧开始播放声音
//_audioSource.enabled = true;
_audioSource.Play();
_mask.gameObject.SetActive(false);
}
}
else
{
//走正常播放流程
_videoPlayer.url = url;
_videoPlayer.renderMode = VideoRenderMode.CameraFarPlane;
_videoPlayer.audioOutputMode = VideoAudioOutputMode.AudioSource;
//_videoPlayer.EnableAudioTrack(0, true);
_videoPlayer.controlledAudioTrackCount = 1;
_videoPlayer.SetTargetAudioSource(0, _audioSource);
//这里一定要让以上工作完成后才能开始准备videoPlayer
_videoPlayer.Prepare();
while (!_videoPlayer.isPrepared)
{
//Debug.Log("Preparing Video");
yield return null;
}
_videoPlayer.Play();
//_audioSource.enabled = false;
//视频播放成功了隐藏mask
//_mask.gameObject.SetActive(false);
//yield return null;
//等待一帧开始播放声音
_audioSource.enabled = true;
_audioSource.Play();
if (_preparedCallBack != null)
{
_preparedCallBack();
_preparedCallBack = null;
}
_mask.gameObject.SetActive(false);
}
}
//显示背景mask遮挡texture
private void ShowMaskTexture()
{
string name = string.Empty;
int random = Random.Range(0, TEXTURE_COUNT);
switch (random)
{
case 0:
name = TEX_MASK_0;
break;
case 1:
name = TEX_MASK_1;
break;
case 2:
name = TEX_MASK_2;
break;
case 3:
name = TEX_MASK_3;
break;
}
Texture tex = GetTextureFromCache(name);
if (tex != null)
{
Renderer rd = _mask.GetComponent<Renderer>();
if (rd != null)
{
if (rd.sharedMaterial == null)
{
Shader sh = PrefabAssetRuntimeUtil.FindShader("Unlit/Transparent Colored");
rd.sharedMaterial = new Material(sh);
}
rd.sharedMaterial.mainTexture = tex;
}
_mask.gameObject.SetActive(true);
}
}
//从缓存中获取背景texture
private Texture GetTextureFromCache(string name)
{
Texture tex = null;
if (_texCache.ContainsKey(name))
{
tex = _texCache[name];
}
else
{
//加载texture
tex = LoadTexture(name);
_texCache.Add(name, tex);
}
return tex;
}
//加载mask 图片
private Texture LoadTexture(string name)
{
Texture tex = null;
//获取当前平台
string path = FixTexturePath(name);
string streamingPath = string.Empty;
string filePath = string.Empty;
#if FUNCELL_LAUNCHER
MyRuntimePlatform runtimePlatform = LauncherManager.Instance.Data.RuntimePlatform;
switch (runtimePlatform)
{
case MyRuntimePlatform.Standalone:
case MyRuntimePlatform.AndroidEditor:
case MyRuntimePlatform.IOSEditor:
case MyRuntimePlatform.StandaloneEditor:
filePath = string.Format("{0}/{1}.jpg", Application.dataPath, path);
//创建文件流
FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
fileStream.Seek(0, SeekOrigin.Begin);
//创建文件长度的缓冲区
byte[] bytes = new byte[fileStream.Length];
//读取文件
fileStream.Read(bytes, 0, (int)fileStream.Length);
//释放文件读取liu
fileStream.Close();
fileStream.Dispose();
fileStream = null;
//创建Texture
int width = 1136;
int height = 640;
Texture2D texture2D = new Texture2D(width, height);
texture2D.LoadImage(bytes);
//texture2D.Resize(1136, 640);
tex = texture2D;
break;
case MyRuntimePlatform.IOS:
case MyRuntimePlatform.Android:
//判断图片是否在转移目录里面
streamingPath = string.Format("{0}/StreamingAssets", Application.persistentDataPath);
filePath = string.Format("{0}/Assets/{1}.unity3d", streamingPath, path);
if (!File.Exists(filePath))
{
//如果不在转移目录里面 那么从apk中读取
string relationPath = path;
if (IsFileInApk(relationPath))
{
streamingPath = Application.streamingAssetsPath;
filePath = string.Format("{0}/Assets/{1}", streamingPath, path);
}
else
{
filePath = string.Empty;
}
}
if (!string.IsNullOrEmpty(filePath))
{
AssetBundle ab = AssetBundle.LoadFromFile(filePath);
tex = (Texture)ab.LoadAsset(name);
}
break;
default:
break;
}
#else
filePath = string.Format("{0}/{1}.jpg", Application.dataPath, path);
//创建文件流
FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
fileStream.Seek(0, SeekOrigin.Begin);
//创建文件长度的缓冲区
byte[] bytes = new byte[fileStream.Length];
//读取文件
fileStream.Read(bytes, 0, (int)fileStream.Length);
//释放文件读取liu
fileStream.Close();
fileStream.Dispose();
fileStream = null;
//创建Texture
int width = 1136;
int height = 640;
Texture2D texture2D = new Texture2D(width, height);
texture2D.LoadImage(bytes);
//texture2D.Resize(1136, 640);
tex = texture2D;
#endif
return tex;
}
private void Update()
{
if (_videoPlayer != null && _videoPlayer.isPrepared)
{
if ((ulong)_videoPlayer.frame >= _videoPlayer.frameCount)
{
if (!_videoPlayer.isLooping)
{
//当前播放的视频已经播放完毕了
//隐藏视频播放节点
if (_finishCallBack != null)
{
_finishCallBack();
_finishCallBack = null;
gameObject.SetActive(false);
}
}
}
}
}
//设置相机depth
public void SetCamraDepth(float d)
{
if (_camera != null)
{
_camera.depth = d;
}
}
#endregion
}