我正在创建一个Gear VR Android应用程序,可以播放30分钟的大型视频。我已经读到我不应该使用StreamingAssets文件夹,但我没有看到任何关于我应该使用什么的信息。如果我将视频放在资产/视频中,它不会包含在 android 版本中。我应该使用资源文件夹还是有其他方法可以包含视频?(我的项目也在iOS上,但我目前在该平台上没有任何问题。
我已经读过可以使用 PersistentDataPath 文件夹,但我不知道如何在从 Unity 中将我的视频放入该文件夹。我不想在那里复制视频,并且只使用一个文件时有两个 600mb 文件。
大文件可能需要很长时间才能提取和复制,有时它们 甚至可能导致设备存储空间或内存不足
这是真的,但你必须知道你在做什么。您不能只使用WWW
API 或仅使用File.Copy
/File.WriteAllBytes
函数复制文件。
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. 资源文件夹。(不推荐(,因为这会减慢您的游戏加载时间。值得一提。使用新的 UnityVideoPlayer
,您可以像这样加载视频:
VideoClip video = Resources.Load("videoFile", typeof(VideoClip)) as VideoClip;
AVPro 插件不是必需的,Unity 中也不再需要它。
如果需要,您还可以将资源文件夹与AVPro插件一起使用。
只需将视频扩展名更改为.bytes
然后将其加载为字节即可。如果AVPro插件可以以字节形式播放视频,那么您就可以了!
TextAsset txtAsset = (TextAsset)Resources.Load("videoFile", typeof(TextAsset));
byte[] videoFile = txtAsset.bytes;
3.使用资产包加载视频。过去,当新的视频 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;
}
4.最后,使用StreamingAssets
文件夹,但不要复制视频,而是创建一个具有HttpListener
的本地服务器并将其指向StreamingAssets
路径。
现在,使用新VideoPlayer
连接到 并播放视频。您可以在堆栈溢出上找到许多HttpListener
服务器的示例。我过去做过这个,它奏效了。
我发现这是一种下载文件并将其保存到PersistantDataPath的方法。 http://answers.unity3d.com/questions/322526/downloading-big-files-on-ios-www-will-give-out-of.html
我看到的一个问题是,如果应用程序暂停。(例如,摘下耳机。下载失败。对于 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);
}