C# 在Unity项目的Gear VR中播放大型视频文件
我正在创建一个Gear VR android应用程序,可以播放30分钟的大视频。我已经读到我不应该使用StreamingAssets文件夹,但是我没有看到任何关于我应该使用什么的信息。如果我把视频放在资产/视频中,它不会包含在android构建中。我应该使用resources文件夹还是有其他方法包含视频?(我的项目也在iOS上,但我目前在该平台上没有任何问题。) 我已经读到可以使用PersistentDataPath文件夹,但我不知道如何将我的视频从unity放入该文件夹。我不想复制那里的视频,当只有一个使用时,我有两个600mb的文件 提取和复制大型文件可能需要很长时间,有时它们会 甚至可能导致设备耗尽存储空间或内存 这是真的,但你必须知道你在做什么。您不能仅使用C# 在Unity项目的Gear VR中播放大型视频文件,c#,file,unity3d,unity5,gear-vr,C#,File,Unity3d,Unity5,Gear Vr,我正在创建一个Gear VR android应用程序,可以播放30分钟的大视频。我已经读到我不应该使用StreamingAssets文件夹,但是我没有看到任何关于我应该使用什么的信息。如果我把视频放在资产/视频中,它不会包含在android构建中。我应该使用resources文件夹还是有其他方法包含视频?(我的项目也在iOS上,但我目前在该平台上没有任何问题。) 我已经读到可以使用PersistentDataPath文件夹,但我不知道如何将我的视频从unity放入该文件夹。我不想复制那里的视频,
WWW
API或仅使用file.copy
/file.writealBytes
函数复制文件
1。将视频分块复制,然后播放。这将消除内存不足问题
bool copyLargeVideoToPersistentDataPath(string videoNameWithExtensionName)
{
string path = Path.Combine(Application.streamingAssetsPath, videoNameWithExtensionName);
string persistentPath = Path.Combine(Application.persistentDataPath, "Videos");
persistentPath = Path.Combine(persistentPath, videoNameWithExtensionName);
bool success = true;
try
{
using (FileStream fromFile = new FileStream(path, FileMode.Open, FileAccess.Read))
{
using (FileStream toFile = new FileStream(persistentPath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
byte[] buffer = new byte[32 * 1024];
int bytesRead;
while ((bytesRead = fromFile.Read(buffer, 0, buffer.Length)) != 0)
{
toFile.Write(buffer, 0, bytesRead);
}
Debug.Log("Done! Saved to Dir: " + persistentPath);
Debug.Log(videoNameWithExtensionName + " Successfully Copied Video to " + persistentPath);
text.text = videoNameWithExtensionName + " Successfully Copied Video to " + persistentPath;
}
}
}
catch (Exception e)
{
Debug.Log(videoNameWithExtensionName + " Failed To Copy Video. Reason: " + e.Message);
text.text = videoNameWithExtensionName + " Failed To Copy Video. Reason: " + e.Message;
success = false;
}
return success;
}
我不想把视频复制到那里,然后在播放时有两个600mb的文件 只使用一个 以下是您拥有的其他选项: 2。文件夹。(不推荐)因为这会减慢游戏加载时间。值得一提。使用新的Unity,您可以像这样加载视频:
VideoClip video = Resources.Load("videoFile", typeof(VideoClip)) as VideoClip;
AVPro插件是不需要的,在Unity中不再需要
如果您需要的话,您也可以使用带有AVPro插件的Resources文件夹 只需将视频扩展名更改为
.bytes
,然后将其作为字节加载即可。如果AVPro插件可以以字节的形式播放视频,那就好了
TextAsset txtAsset = (TextAsset)Resources.Load("videoFile", typeof(TextAsset));
byte[] videoFile = txtAsset.bytes;
3。使用AssetBundle加载视频。这在过去新的视频API问世时不受支持,但现在应该得到支持
IEnumerable LoadObject(string path)
{
AssetBundleCreateRequest bundle = AssetBundle.LoadFromFileAsync(path);
yield return bundle;
AssetBundle myLoadedAssetBundle = bundle.assetBundle;
if (myLoadedAssetBundle == null)
{
Debug.Log("Failed to load AssetBundle!");
yield break;
}
AssetBundleRequest request = myLoadedAssetBundle.LoadAssetAsync<GameObject>("VideoFile");
yield return request;
VideoClip clip = request.asset as VideoClip;
}
IEnumerable加载对象(字符串路径)
{
AssetBundleCreateRequestBundle=AssetBundle.LoadFromFileAsync(路径);
收益-收益捆绑;
AssetBundle myLoadedAssetBundle=bundle.AssetBundle;
if(myLoadedAssetBundle==null)
{
Log(“加载资产绑定失败!”);
屈服断裂;
}
AssetBundlerRequest请求=myLoadedAssetBundle.LoadAssetAsync(“视频文件”);
退换货请求;
VideoClip clip=请求.asset作为VideoClip;
}
4。最后,使用
StreamingAssets
文件夹,但不要复制视频,而是使用HttpListener
创建一个本地服务器,并将其指向StreamingAssets
路径
现在,连接新功能并播放视频。您可以在stackoverflow上找到许多HttpListener
服务器的示例。我过去也做过这件事,而且效果很好
提取和复制大型文件可能需要很长时间,有时它们会
甚至可能导致设备耗尽存储空间或内存
这是真的,但你必须知道你在做什么。您不能仅使用WWW
API或仅使用file.copy
/file.writealBytes
函数复制文件
1。将视频分块复制,然后播放。这将消除内存不足问题
bool copyLargeVideoToPersistentDataPath(string videoNameWithExtensionName)
{
string path = Path.Combine(Application.streamingAssetsPath, videoNameWithExtensionName);
string persistentPath = Path.Combine(Application.persistentDataPath, "Videos");
persistentPath = Path.Combine(persistentPath, videoNameWithExtensionName);
bool success = true;
try
{
using (FileStream fromFile = new FileStream(path, FileMode.Open, FileAccess.Read))
{
using (FileStream toFile = new FileStream(persistentPath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
byte[] buffer = new byte[32 * 1024];
int bytesRead;
while ((bytesRead = fromFile.Read(buffer, 0, buffer.Length)) != 0)
{
toFile.Write(buffer, 0, bytesRead);
}
Debug.Log("Done! Saved to Dir: " + persistentPath);
Debug.Log(videoNameWithExtensionName + " Successfully Copied Video to " + persistentPath);
text.text = videoNameWithExtensionName + " Successfully Copied Video to " + persistentPath;
}
}
}
catch (Exception e)
{
Debug.Log(videoNameWithExtensionName + " Failed To Copy Video. Reason: " + e.Message);
text.text = videoNameWithExtensionName + " Failed To Copy Video. Reason: " + e.Message;
success = false;
}
return success;
}
我不想把视频复制到那里,然后在播放时有两个600mb的文件 只使用一个 以下是您拥有的其他选项: 2。文件夹。(不推荐)因为这会减慢游戏加载时间。值得一提。使用新的Unity,您可以像这样加载视频:
VideoClip video = Resources.Load("videoFile", typeof(VideoClip)) as VideoClip;
AVPro插件是不需要的,在Unity中不再需要
如果您需要的话,您也可以使用带有AVPro插件的Resources文件夹 只需将视频扩展名更改为
.bytes
,然后将其作为字节加载即可。如果AVPro插件可以以字节的形式播放视频,那就好了
TextAsset txtAsset = (TextAsset)Resources.Load("videoFile", typeof(TextAsset));
byte[] videoFile = txtAsset.bytes;
3。使用AssetBundle加载视频。这在过去新的视频API问世时不受支持,但现在应该得到支持
IEnumerable LoadObject(string path)
{
AssetBundleCreateRequest bundle = AssetBundle.LoadFromFileAsync(path);
yield return bundle;
AssetBundle myLoadedAssetBundle = bundle.assetBundle;
if (myLoadedAssetBundle == null)
{
Debug.Log("Failed to load AssetBundle!");
yield break;
}
AssetBundleRequest request = myLoadedAssetBundle.LoadAssetAsync<GameObject>("VideoFile");
yield return request;
VideoClip clip = request.asset as VideoClip;
}
IEnumerable加载对象(字符串路径)
{
AssetBundleCreateRequestBundle=AssetBundle.LoadFromFileAsync(路径);
收益-收益捆绑;
AssetBundle myLoadedAssetBundle=bundle.AssetBundle;
if(myLoadedAssetBundle==null)
{
Log(“加载资产绑定失败!”);
屈服断裂;
}
AssetBundlerRequest请求=myLoadedAssetBundle.LoadAssetAsync(“视频文件”);
退换货请求;
VideoClip clip=请求.asset作为VideoClip;
}
4。最后,使用
StreamingAssets
文件夹,但不要复制视频,而是使用HttpListener
创建一个本地服务器,并将其指向StreamingAssets
路径
现在,连接新功能并播放视频。您可以在stackoverflow上找到许多
HttpListener
服务器的示例。我以前也这样做过,而且很有效。我发现这是一种下载文件并将其保存到PersistantDataPath的方法。
我看到的一个问题是,如果应用程序暂停。(例如,取下耳机)下载失败。对于650MB的文件,基本上所有用户都会这样。你知道我如何在unity暂停时继续下载吗?我还将对此发表一篇新文章。我发现这是一种下载文件并将其保存到PersistantDataPath的方法。
我看到的一个问题是,如果应用程序暂停。(例如,取下耳机)下载失败。对于650MB的文件,基本上所有用户都会这样。你知道我如何在unity暂停时继续下载吗?我还将就此发表一篇新文章。这是我现在要用的代码
void DownloadFile()
{
loadingBar.gameObject.SetActive(true);
downloadButton.SetActive(false);
downloadingFile = true;
WebClient client = new WebClient();
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
client.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(DownloadFileCompleted);
client.DownloadFileAsync(new Uri(url), Application.persistentDataPath + "/" + fileName);
}
void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
double bytesIn = double.Parse(e.BytesReceived.ToString());
double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
double percentage = bytesIn / totalBytes * 100;
downloadProgressText = "Downloaded " + e.BytesReceived + " of " + e.TotalBytesToReceive;
downloadProgress = int.Parse(Math.Truncate(percentage).ToString());
totalBytes = e.TotalBytesToReceive;
bytesDownloaded = e.BytesReceived;
}
void DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
if (e.Error == null)
{
AllDone();
}
}
void AllDone()
{
Debug.Log("File Downloaded");
FileExists = 1;
}
public void DeleteVideo()
{
print("Delete File");
PlayerPrefs.DeleteKey("videoDownloaded");
FileExists = 0;
enterButton.SetActive(false);
downloadButton.SetActive(true);
File.Delete(Application.persistentDataPath + "/" + fileName);
}
这是我现在要用的代码
void DownloadFile()
{
loadingBar.gameObject.SetActive(true);
downloadButton.SetActive(false);
downloadingFile = true;
WebClient client = new WebClient();
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
client.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(DownloadFileCompleted);
client.DownloadFileAsync(new Uri(url), Application.persistentDataPath + "/" + fileName);
}
void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
double bytesIn = double.Parse(e.BytesReceived.ToString());
double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
double percentage = bytesIn / totalBytes * 100;
downloadProgressText = "Downloaded " + e.BytesReceived + " of " + e.TotalBytesToReceive;
downloadProgress = int.Parse(Math.Truncate(percentage).ToString());
totalBytes = e.TotalBytesToReceive;
bytesDownloaded = e.BytesReceived;
}
void DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
if (e.Error == null)
{
AllDone();
}
}
void AllDone()
{
Debug.Log("File Downloaded");
FileExists = 1;
}
public void DeleteVideo()
{
print("Delete File");
PlayerPrefs.DeleteKey("videoDownloaded");
FileExists = 0;
enterButton.SetActive(false);
downloadButton.SetActive(true);
File.Delete(Application.persistentDataPath + "/" + fileName);
}
“我已经读到我不应该使用流媒体