2025-01-25 04:38:09 +08:00

689 lines
22 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}