对Http访问操作,Unity中一般使用协程操作,但是协程有一个比较要命的要求就是所在Mono必须在场景中是激活的,所以一些操作就会被限制。所以我们就找办法替代掉协程做一些异步的操作。那就用异步方法。
首先扩展一下AsyncOperation类型。
//扩展方法应该写在静态类里
public static class HttpPlus
{
/// <summary>
/// 异步重载
/// </summary>
/// <param name="asyncOp"></param>
/// <returns></returns>
public static TaskAwaiter GetAwaiter(this AsyncOperation asyncOp)
{
var tcs = new TaskCompletionSource<object>();
asyncOp.completed += obj => { tcs.SetResult(null); };
return ((Task) tcs.Task).GetAwaiter();
}
}
然后就开始编写HTTP请求代码。
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.Networking;
public class DownloadDataHandle
{
public int code;
public string msg;
public object data;
}
public class MNull
{
}
public static class HttpPlus
{
/// <summary>
/// 异步重载
/// </summary>
/// <param name="asyncOp"></param>
/// <returns></returns>
public static TaskAwaiter GetAwaiter(this AsyncOperation asyncOp)
{
var tcs = new TaskCompletionSource<object>();
asyncOp.completed += obj => { tcs.SetResult(null); };
return ((Task) tcs.Task).GetAwaiter();
}
}
public class HttpManager
{
/// <summary>
/// 异步Get
/// </summary>
/// <param name="uri"></param>
/// <param name="toDo">数据获取之后执行的回调</param>
/// <typeparam name="T"></typeparam>
internal async void GetAsync<T>(string uri, Action<T, DownloadDataHandle> toDo = null)
{
using var webRequest = UnityWebRequest.Get(uri);
await webRequest.SendWebRequest();
switch (webRequest.result)
{
case UnityWebRequest.Result.ConnectionError:
case UnityWebRequest.Result.DataProcessingError:
case UnityWebRequest.Result.ProtocolError:
case UnityWebRequest.Result.InProgress:
try
{
var handle1 = JsonConvert.DeserializeObject<DownloadDataHandle>(webRequest.downloadHandler.text);
toDo?.Invoke(default, handle1);
}
catch (Exception e)
{
Debug.Log(webRequest.error + " url : " + uri);
}
break;
case UnityWebRequest.Result.Success:
try
{
var handle = JsonConvert.DeserializeObject<DownloadDataHandle>(webRequest.downloadHandler.text);
var t = typeof(T) == typeof(MNull) ? default : JsonConvert.DeserializeObject<T>(handle.data.ToString());
toDo?.Invoke(t, handle);
}
catch (Exception e)
{
Debug.Log("e : " + e);
}
break;
}
}
/// <summary>
/// 异步获取图片
/// </summary>
/// <param name="uri">地址</param>
/// <param name="size">传进来的图片尺寸</param>
/// <param name="toDo">把sprite和Texture2D一起返回方便管理(在使用后销毁)</param>
internal async void GetImg(string uri, Vector2Int size, Action<Sprite, Texture2D> toDo = null)
{
using var webRequest = UnityWebRequest.Get(uri);
await webRequest.SendWebRequest();
switch (webRequest.result)
{
case UnityWebRequest.Result.InProgress:
case UnityWebRequest.Result.ConnectionError:
case UnityWebRequest.Result.ProtocolError:
case UnityWebRequest.Result.DataProcessingError:
Debug.Log(webRequest.error + " url : " + uri);
break;
case UnityWebRequest.Result.Success:
// 先获取到图片的数据
byte[] results = webRequest.downloadHandler.data;
// 创建一个 Texture,这个尺寸根据自己需要而定
Texture2D texture = new Texture2D(size.x, size.y);
texture.LoadImage(results);
await Task.Delay(10);
// 使用 Texture 创建一个sprite
Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
toDo?.Invoke(sprite, texture);
break;
}
}
/// <summary>
/// 异步Post
/// </summary>
/// <param name="uri">地址</param>
/// <param name="form">表单</param>
/// <param name="header">头</param>
/// <param name="toDo">数据上传之后执行的回调</param>
/// <typeparam name="T"></typeparam>
internal async void PostAsync<T>(string uri, WWWForm form, Dictionary<string, string> header = null, Action<T, DownloadDataHandle> toDo = null)
{
using var webRequest = UnityWebRequest.Post(uri, form);
if (header != null)
{
foreach (var item in header)
{
webRequest.SetRequestHeader(item.Key, item.Value);
}
}
await webRequest.SendWebRequest();
switch (webRequest.result)
{
case UnityWebRequest.Result.ConnectionError:
case UnityWebRequest.Result.DataProcessingError:
case UnityWebRequest.Result.InProgress:
case UnityWebRequest.Result.ProtocolError:
try
{
var handle = JsonConvert.DeserializeObject<DownloadDataHandle>(webRequest.downloadHandler.text);
toDo?.Invoke(default, handle);
}
catch (Exception e)
{
Debug.Log(webRequest.error + " , " + uri + " e : " + e);
}
break;
case UnityWebRequest.Result.Success:
try
{
var handle = JsonConvert.DeserializeObject<DownloadDataHandle>(webRequest.downloadHandler.text);
var t = typeof(T) == typeof(MNull) ? default : JsonConvert.DeserializeObject<T>(handle.data.ToString());
toDo?.Invoke(t, handle);
}
catch (Exception e)
{
Debug.LogError("e : " + e);
}
break;
}
}
}
这样就可以了。