using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
/// <summary>
/// web请求管理器
/// </summary>
public class UnityWebRequestMgr : SingletonMono<UnityWebRequestMgr>
{
#region 公开函数
public void Get(string url, Action<UnityWebRequest> actionResult)
{
StartCoroutine(GetAsyn(url, actionResult));
}
public void DownloadFile(string url, string downloadFilePathAndName, Action<UnityWebRequest> actionResult)
{
StartCoroutine(DownloadFileAsyn(url, downloadFilePathAndName, actionResult));
}
public void GetTexture(string url, Action<Texture2D> actionResult)
{
StartCoroutine(GetTextureAsyn(url, actionResult));
}
public void GetText(string url, Action<string> actionResult)
{
StartCoroutine(GetTextAsyn(url, actionResult));
}
public void GetAssetBundle(string url, Action<AssetBundle> actionResult)
{
StartCoroutine(GetAssetBundleAsyn(url, actionResult));
}
public void GetAudioClip(string url, Action<AudioClip> actionResult, AudioType audioType = AudioType.WAV)
{
StartCoroutine(GetAudioClipAsyn(url, actionResult, audioType));
}
public void Post(string serverURL, List<IMultipartFormSection> lstformData,
Action<UnityWebRequest> actionResult)
{
StartCoroutine(PostAsyn(serverURL, lstformData, actionResult));
}
public void UploadByPut(string url, byte[] contentBytes, Action<bool> actionResult)
{
StartCoroutine(UploadByPutAsyn(url, contentBytes, actionResult, ""));
}
public void Delete(string url, Action<UnityWebRequest> actionResult)
{
StartCoroutine(DeletedAsyn(url, actionResult));
}
#endregion
#region 私有函数
private IEnumerator GetAsyn(string url, Action<UnityWebRequest> actionResult)
{
using (UnityWebRequest uwr = UnityWebRequest.Get(url))
{
yield return uwr.SendWebRequest();
actionResult?.Invoke(uwr);
}
}
private IEnumerator DownloadFileAsyn(string url, string downloadFilePathAndName,
Action<UnityWebRequest> actionResult)
{
var uwr = new UnityWebRequest(url, UnityWebRequest.kHttpVerbGET);
uwr.downloadHandler = new DownloadHandlerFile(downloadFilePathAndName);
yield return uwr.SendWebRequest();
actionResult?.Invoke(uwr);
}
private IEnumerator GetTextureAsyn(string url, Action<Texture2D> actionResult)
{
UnityWebRequest uwr = new UnityWebRequest(url);
DownloadHandlerTexture downloadTexture = new DownloadHandlerTexture(true);
uwr.downloadHandler = downloadTexture;
yield return uwr.SendWebRequest();
Texture2D t = null;
if (!(uwr.isNetworkError || uwr.isHttpError))
{
t = downloadTexture.texture;
}
if (t == null) Debug.LogError(GetType() + "GetTextureAsyn()/ Get Texture is error! url:" + url);
actionResult?.Invoke(t);
}
private IEnumerator GetTextAsyn(string url, Action<string> actionResult)
{
UnityWebRequest request = UnityWebRequest.Get(url);
yield return request.SendWebRequest();
string t = request.downloadHandler.text;
if (string.IsNullOrEmpty(t)) Debug.LogError(GetType() + "GetTextAsyn()/ Get Text is error! url:" + url);
actionResult?.Invoke(t);
}
private IEnumerator GetAssetBundleAsyn(string url, Action<AssetBundle> actionResult)
{
UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(url);
yield return request.SendWebRequest();
AssetBundle ab = (request.downloadHandler as DownloadHandlerAssetBundle)?.assetBundle;
if (ab == null)
{
Debug.Log("Failed to load AssetBundle!");
yield break;
}
actionResult?.Invoke(ab);
}
private IEnumerator GetAudioClipAsyn(string url, Action<AudioClip> actionResult,
AudioType audioType = AudioType.WAV)
{
using (var uwr = UnityWebRequestMultimedia.GetAudioClip(url, audioType))
{
yield return uwr.SendWebRequest();
if (!(uwr.isNetworkError || uwr.isHttpError))
{
if (actionResult != null)
{
actionResult(DownloadHandlerAudioClip.GetContent(uwr));
}
}
else Debug.LogError(GetType() + "GetAudioClipAsyn()/ Get AudioClip is error! url:" + url);
}
}
private IEnumerator PostAsyn(string serverURL, List<IMultipartFormSection> lstformData,
Action<UnityWebRequest> actionResult)
{
UnityWebRequest uwr = UnityWebRequest.Post(serverURL, lstformData);
yield return uwr.SendWebRequest();
actionResult?.Invoke(uwr);
}
private IEnumerator UploadByPutAsyn(string url, byte[] contentBytes, Action<bool> actionResult,
string contentType = "application/octet-stream")
{
UnityWebRequest uwr = new UnityWebRequest();
UploadHandler uploader = new UploadHandlerRaw(contentBytes);
uploader.contentType = contentType;
uwr.uploadHandler = uploader;
yield return uwr.SendWebRequest();
bool res = !(uwr.isNetworkError || uwr.isHttpError);
actionResult?.Invoke(res);
}
private IEnumerator DeletedAsyn(string url, Action<UnityWebRequest> actionResult)
{
using (UnityWebRequest uwr = UnityWebRequest.Delete(url))
{
yield return uwr.SendWebRequest();
actionResult?.Invoke(uwr);
}
}
#endregion
}
单例脚本
public abstract class SingletonMono<T> : MonoBehaviour where T : SingletonMono<T>
{
protected static T _Instance = null;
public static T Instance
{
get
{
if (null == _Instance)
{
//寻找是否存在当前单例类对象
_Instance = FindObjectOfType<T>();
//不存在的话
if (_Instance == null)
{
//new一个并添加一个单例脚本
_Instance = new GameObject(typeof(T).Name).AddComponent<T>();
}
else
{
_Instance.Init();
}
//在切换场景的时候不要释放这个对象
DontDestroyOnLoad(_Instance.gameObject);
}
return _Instance;
}
}
private void Awake()
{
if (_Instance == null) //如果未实例化
{
_Instance = this as T; //as T 指强转 为 派生类 传递进来的 类型
Init(); //为实现 派生类继承 单例模式基类时 无法使用 Awake() 方法采用 Init() 虚方法 代替
}
}
/// <summary>
/// MonoSingleton 基类 留给派生类做Awake()初始化的方法[虚方法]
/// </summary>
protected virtual void Init()
{
}
}
使用方式
在场景创建一个空物体,创建一个Image,将面的测试脚本挂在到空物体上,将Image赋值给空物体上的脚本,即可执行代码
播放视频使用的是Unity自带的VideoPlayer需要自己创建播放的资源。
using Manager;
using System;
using System.IO;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
public class MyTestScript : MonoBehaviour
{
public Image myImage;
private void Start()
{
//发布为webgl之后读取stramingAssets下的文件
ReadText();
//发送get请求
SendGet();
//下载文件
DownloadFile();
//异步下载一个texture2d并应用
GetTextureAsyn();
//下载音频到本地并播放
GetAudioClip();
//下载视频到本地并播放
GetVideoClip();
}
/// <summary>
/// 读取文件
/// </summary>
private void ReadText()
{
var textConntent = new System.Uri(Path.Combine(
Application.streamingAssetsPath + @"/Config", "helloman.txt"));
UnityWebRequestMgr.Instance.GetText(textConntent.ToString(), (temp) =>
{
if (!String.IsNullOrWhiteSpace(temp))
{
Debug.Log("读取到steamAssets下的配置文件helloman.txt,内容是\n" + temp);
}
else
{
Debug.Log("加载配置文件错误");
}
});
}
/// <summary>
/// 发送get请求
/// </summary>
private void SendGet()
{
string BaiDu_Url = "www.baidu.com";
UnityWebRequestMgr.Instance.Get(BaiDu_Url, (htmlConntent) =>
{
Debug.Log("发送get请求获取到的页面文件是:" + htmlConntent.downloadHandler.text);
});
}
/// <summary>
/// 下载文件
/// </summary>
private void DownloadFile()
{
string DownLoad_url = "http://b.hiphotos.baidu.com/image/pic/item/359b033b5bb5c9ea5c0e3c23d139b6003bf3b374.jpg";
string LocalPath = Application.streamingAssetsPath + "/hello.jpg";
UnityWebRequestMgr.Instance.DownloadFile(DownLoad_url, LocalPath, (imageRequest) =>
{
if (imageRequest.result == UnityWebRequest.Result.Success)
{
Debug.Log("文件下载成功,保存在: " + LocalPath);
}
else
{
Debug.LogError("文件下载失败: " + imageRequest.error);
}
Debug.Log("文件下载完毕");
});
}
/// <summary>
/// 下载一个贴图
/// </summary>
private void GetTextureAsyn()
{
string DownLoad_url = "http://b.hiphotos.baidu.com/image/pic/item/359b033b5bb5c9ea5c0e3c23d139b6003bf3b374.jpg";
UnityWebRequestMgr.Instance.GetTexture(DownLoad_url, (texture2D) =>
{
// 创建一个Sprite,使用Texture2D来作为基础
Sprite sprite = Sprite.Create(texture2D, new Rect(0, 0, texture2D.width, texture2D.height), new Vector2(0.5f, 0.5f));
// 将Sprite赋值给Image组件
myImage.sprite = sprite;
// 可选,如果需要调整图像的填充模式
myImage.type = Image.Type.Sliced; // 或Simple, Tiled, Filled等
// 可选,如果需要调整图像的填充方式
myImage.preserveAspect = true; // 保持纵横比
});
}
/// <summary>
/// 下载并播放一段音频
/// </summary>
private void GetAudioClip()
{
string Audio_Url = "https://download.samplelib.com/wav/sample-3s.wav";
UnityWebRequestMgr.Instance.GetAudioClip(Audio_Url, (audioClip) =>
{
var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.AddComponent<AudioSource>();
var cubuAudio = cube.GetComponent<AudioSource>();
cubuAudio.clip = audioClip;
cubuAudio.Play();
string path = Application.streamingAssetsPath + "\\audio1.wav";
AudioSaveLocal audioSaveLocal = new AudioSaveLocal();
audioSaveLocal.Save("dududu", audioClip);
});
}
/// <summary>
/// 获取视频
/// </summary>
private void GetVideoClip()
{
string video_url = "https://samplelib.com/zh/sample-mp4.html";
}
}
/// <summary>
/// 将下载的audioClip写入到本地
/// </summary>
class AudioSaveLocal
{
/// <summary>
/// 录音文件保存
/// </summary>
const int HEADER_SIZE = 44;
public void Save(string fileName, AudioClip clip)
{
if (!fileName.ToLower().EndsWith(".wav"))
{
fileName += ".wav";
}
string filePath = Path.Combine(Application.streamingAssetsPath + "/InteractVideo/Music", fileName);
if (Directory.Exists(filePath))
{
Directory.Delete(filePath, true);
}
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
Debug.Log(filePath);
//创建头
FileStream fs = CreateEmpty(filePath);
//写语音数据
ConvertAndWrite(fs, clip);
//重写真正的文件头
WriteHeader(fs, clip);
fs.Flush();
fs.Close();
Debug.Log("声音已经保存到本地,路径是:" + Path.Combine(Application.streamingAssetsPath + "/InteractVideo/Music", fileName));
}
/// <summary>
/// 创建头
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
FileStream CreateEmpty(string filePath)
{
var fileStream = new FileStream(filePath, FileMode.Create);
byte emptyByte = new byte();
for (int i = 0; i < HEADER_SIZE; i++)
{
fileStream.WriteByte(emptyByte);
}
return fileStream;
}
/// <summary>
/// 写音频数据
/// </summary>
/// <param name="fileSteam"></param>
/// <param name="clip"></param>
void ConvertAndWrite(FileStream fileSteam, AudioClip clip)
{
var samples = new float[clip.samples];
clip.GetData(samples, 0);
Int16[] intData = new Int16[samples.Length];
Byte[] bytesData = new Byte[samples.Length * 2];
int rescaleFactor = 32767;
for (int i = 0; i < samples.Length; i++)
{
intData[i] = (short)(samples[i] * rescaleFactor);
Byte[] byteArray = new byte[2];
byteArray = BitConverter.GetBytes(intData[i]);
byteArray.CopyTo(bytesData, i * 2);
}
fileSteam.Write(bytesData, 0, bytesData.Length);
}
/// <summary>
/// 重写真正的文件头
/// </summary>
/// <param name="fileStream"></param>
/// <param name="clip"></param>
void WriteHeader(FileStream fileStream, AudioClip clip)
{
var hz = clip.frequency;
var channels = clip.channels;
var samples = clip.samples;
fileStream.Seek(0, SeekOrigin.Begin);
Byte[] riff = System.Text.Encoding.UTF8.GetBytes("RIFF");
fileStream.Write(riff, 0, 4);
Byte[] chunkSize = BitConverter.GetBytes(fileStream.Length - 8);
fileStream.Write(chunkSize, 0, 4);
Byte[] wave = System.Text.Encoding.UTF8.GetBytes("WAVE");
fileStream.Write(wave, 0, 4);
Byte[] fmt = System.Text.Encoding.UTF8.GetBytes("fmt ");
fileStream.Write(fmt, 0, 4);
Byte[] subChunk1 = BitConverter.GetBytes(16);
fileStream.Write(subChunk1, 0, 4);
Byte[] audioFormat = BitConverter.GetBytes(1);
fileStream.Write(audioFormat, 0, 2);
Byte[] numChannels = BitConverter.GetBytes(channels);
fileStream.Write(numChannels, 0, 2);
Byte[] sampleRate = BitConverter.GetBytes(hz);
fileStream.Write(sampleRate, 0, 4);
Byte[] byRate = BitConverter.GetBytes(hz * channels * 2);
fileStream.Write(byRate, 0, 4);
UInt16 blockAlign = (ushort)(channels * 2);
fileStream.Write(BitConverter.GetBytes(blockAlign), 0, 2);
UInt16 bps = 16;
Byte[] bitsPerSample = BitConverter.GetBytes(bps);
fileStream.Write(bitsPerSample, 0, 2);
Byte[] dataString = System.Text.Encoding.UTF8.GetBytes("data");
fileStream.Write(dataString, 0, 4);
Byte[] subChunk2 = BitConverter.GetBytes(samples * channels * 2);
fileStream.Write(subChunk2, 0, 4);
}
}