基于Unity的Hololens2访问下载链接实现Json、模型以及视频流传输(个人Hololens2进阶开发总结)
前言
在之前三期的教学中,我们学会了如何解决在Unity编辑器下开发HoloLens2遇到的一些Bug(文件存储路径问题、读取Json文件问题以及AssertBundle资源管理问题),下面就通过我在项目中做出的一些成果来进行一次实战。前三期教程在下面:
HoloLens下载、读取与存储Json文件路径问题(个人Hololens2进阶开发小总结一)
HoloLens读取和下载Json文件问题(个人Hololens2进阶开发小总结二)
关于Hololens2上AssetBundle资源管理、热更新问题(个人Hololens2进阶开发小总结三)
基于Unity的Hololens2与服务器交互
不管是在实际的开发Hololens2项目中,还是其他游戏等项目都有涉及到热更新这个概念,那么在Hololens2的开发中如果不会lua或者其他的更新方式,只会Unity自带的AB包更新方法,在实际部署到Hololens2时会出现众多问题。以下就以一个简单的案例来展示下一个Hololens2访问视频下载链接与AB包下载链接实现模型、视频流传输的工程。
一、Web端的下载链接
以下是某知乎教如何把视频转换为下载链接
https://www.zhihu.com/question/61371714/answer/2226588590
我们项目实现的目的就是能够在Hololens2中通过获取到的Json文件中给出的该下载链接,向该链接发送下载请求并下载到Hololens2本机的文件资源管理器中,然后进行播放。
二、Json文件的读取
1.Json格式
video.json:存放视频流url
此处的name对应着你要下载的这个视频下载到Hololens2本机中后他的视频名称,后缀为MP4。
url即为你的视频下载链接,打开链接应该是一段播放的视频。
我们需要把你写好的这个Json文件通过Hololens2的后台放进到Application.persistentDataPath
中
像我就是放在这里
AB.json:存放AB包中的四个文件以及下载链接,记住name一定要是你对应AB包内的文件名!
同样AB包也是同样的方式放入Hololens2的后台
2.读取和解析Json
然后我们需要读取到Json文件里面的内容并访问下载链接
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using UnityEngine.Video;
using System.Runtime.Serialization.Formatters.Binary;
[System.Serializable]
class data
{
public string url;
public string name;
}
[System.Serializable]
class Video
{
public data[] data;
}
public class LoadVideo : MonoBehaviour
{
string path = "";
FileStream fs;
public static string ReadData()
{
string readData;
string fileUrl = Application.persistentDataPath + "/VideoJSON/video.json";
using (StreamReader sr = File.OpenText(fileUrl))
{
readData = sr.ReadToEnd();
sr.Close();
}
return readData;
}
public VideoPlayer video;
MeshRenderer mesh;
void Awake()
{
video = this.GetComponent<VideoPlayer>();
mesh = this.GetComponent<MeshRenderer>();
}
private void Start()
{
mesh.enabled = false;
}
public void DownVideo()//该事件绑定在MRTK中的按钮
{
loadingbar.SetActive(true);
string vs = ReadData();
Video v = JsonUtility.FromJson<Video>(vs);
foreach(data a in v.data)
{
Debug.Log(a.name);
Debug.Log(a.url);
StartCoroutine(DownOrLoadVideo(a.name, a.url));
}
}
IEnumerator DownOrLoadVideo(string downloadVideoName, string videoURL)
{
path = Application.persistentDataPath + @"/Video";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
Debug.Log("下载" + path);
WWW www = new WWW(videoURL);
yield return www;
if (!string.IsNullOrEmpty(www.error))
{
Debug.Log("请求失败");
StartCoroutine(DownUnSuccess());
}
else
{
fs = File.Create(path + "/" + downloadVideoName + ".mp4");
fs.Write(www.bytes, 0, www.bytes.Length);
fs.Close();
//path += "/" + downloadVideoName + ".mp4";
//video.url = path;//赋值就能播放了
Debug.Log("视频下载成功");
//mesh.enabled = true;//下载好了就应该可以播放了,但注意如果你下载的不止一个视频,最好就不要这里写播放视频的事件
}
}
}
AB.json的解析方式一样
3.发送下载请求
文章中提出的下载请求方式是WWW请求,这个比较老了,也不知道是不是这个原因导致在部署到Hololens2后发送下载请求进行下载时的速度比较慢,大家可以尝试换成Unity中自带的WebRequest方法
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using UnityEngine;
public class DownLoaderEnum
{
public string url;
public string path;
public DownLoaderEnum(string URL, string PATH)
{
url = URL;
path = PATH;
}
}
public class HttpDownload
{
/// <param name="url">下载文件地址</param>
/// <param name="path">文件存放地址,包含文件名</param>
public void HttpDownloader(object down)
{
if (!Directory.Exists((down as DownLoaderEnum).path))
Directory.CreateDirectory((down as DownLoaderEnum).path);
string tempPath = System.IO.Path.GetDirectoryName((down as DownLoaderEnum).path) + @"\temp";
System.IO.Directory.CreateDirectory(tempPath); //创建临时文件目录
string tempFile = tempPath + @"\" + System.IO.Path.GetFileName((down as DownLoaderEnum).path) + ".temp"; //临时文件
if (System.IO.File.Exists(tempFile))
{
System.IO.File.Delete(tempFile); //存在则删除
}
try
{
FileStream fs = new FileStream(tempFile, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
HttpWebRequest request = WebRequest.Create((down as DownLoaderEnum).url) as HttpWebRequest;
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
Stream responseStream = response.GetResponseStream();
byte[] bArr = new byte[1024];
int size = responseStream.Read(bArr, 0, (int)bArr.Length);
while (size > 0)
{
fs.Write(bArr, 0, size);
size = responseStream.Read(bArr, 0, (int)bArr.Length);
}
fs.Close();
responseStream.Close();
string suffixName = (down as DownLoaderEnum).url;
int su = suffixName.LastIndexOf(\'/\');
suffixName = (down as DownLoaderEnum).path+suffixName.Substring(su);
System.IO.File.Move(tempFile, suffixName);
Debug.LogError("下载完成");
}
catch (Exception ex)
{
Debug.LogError("错误==>>" + ex.Message);
}
}
}
嫌麻烦的朋友就直接用WWW请求,因为不知道Unity自带的请求方式部署到Hololens2上会不会出问题。
4.视频展示
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using UnityEngine;
using UnityEngine.Video;
public class ShowVideo : MonoBehaviour
{
string path = null;
string videoname = null;
public VideoPlayer video;
MeshRenderer mesh;
private void Start() {
path = Application.persistentDataPath + @"/Video";
videoname = "zhuangpei1";//你要播放的视频名称
mesh = this.GetComponent<MeshRenderer>();
}
public void playvideo()//该事件绑定在MRTK中的按钮
{
StartCoroutine(PlayVideo(videoname));
}
IEnumerator PlayVideo(string name)
{
yield return new WaitForSeconds(0.01f);
path = Application.persistentDataPath + @"/Video/" +name + ".mp4";
video.url = path;//赋值就能播放了
mesh.enabled = true;
}
}
5.AssetBundle资源更新与展示
AssetBundle资源更新在上一期已经讲过了,这里就不多阐述,直接展示
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using TMPro;
using System.Xml;
using System.Text;
public class GetAB : MonoBehaviour
{
[System.Serializable]
class data
{
public string url;
public string name;
}
[System.Serializable]
class AB
{
public data[] data;
}
private AssetBundleCreateRequest zhidong;
FileStream fs;
public string savepath = "";
public static string ReadData()
{
string readData;
string fileUrl = Application.persistentDataPath + "/ABJSON/AB.json";
using (StreamReader sr = File.OpenText(fileUrl))
{
readData = sr.ReadToEnd();
sr.Close();
}
return readData;
}
void Start()
{
savepath = Application.persistentDataPath + "/ab";
}
public void startDown()//该事件绑定在MRTK中的按钮
{
string vs = ReadData();
AB ab = JsonUtility.FromJson<AB>(vs);
foreach (data a in ab.data)
{
Debug.Log(a.url);
Debug.Log(a.name);
StartCoroutine(DownAB(a.url, a.name));
}
}
public void startLoad()
{
StartCoroutine(LoadAB());
}
IEnumerator DownAB(string downloadurl,string filename)
{
loadingbar.SetActive(true);
if (!Directory.Exists(savepath))
{
Directory.CreateDirectory(savepath);
}
WWW www = new WWW(downloadurl);
yield return www;
if (!string.IsNullOrEmpty(www.error))
{
Debug.Log("请求失败");
}
else
{
fs = File.Create(savepath + "/" + filename);
fs.Write(www.bytes, 0, www.bytes.Length);
fs.Close();
Debug.Log("下载成功");
}
}
IEnumerator LoadAB()
{
zhidong = AssetBundle.LoadFromFileAsync(savepath + "/zhidong");
yield return zhidong;
}
IEnumerator LoadObject(string assetName)
{
yield return new WaitForSeconds(0.01f);
GameObject chilun = (GameObject)Instantiate(zhidong.assetBundle.LoadAsset(assetName));
}
public void Load()//该事件绑定在MRTK中的按钮
{
StartCoroutine(LoadObject("你的assetName"));
}
}
6.项目演示
下面是我的项目的一些演示:
上图是Hololens2工程在发送WWW请求下载视频的过程
上图是视频和模型的展示。
总结
Hololens2的小案例实现就到此结束
后面博主还会更新更多后续内容…