对Http访问操作,Unity中一般使用协程操作,但是协程有一个比较要命的要求就是所在Mono必须在场景中是激活的,所以一些操作就会被限制。所以我们就找办法替代掉协程做一些异步的操作。那就用异步方法。
首先扩展一下AsyncOperation类型。
//扩展方法应该写在静态类里
public static class HttpPlus
{
///
/// 异步重载
///
///
///
public static TaskAwaiter GetAwaiter(this AsyncOperation asyncOp)
{
var tcs = new TaskCompletionSource();
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
{
///
/// 异步重载
///
///
///
public static TaskAwaiter GetAwaiter(this AsyncOperation asyncOp)
{
var tcs = new TaskCompletionSource();
asyncOp.completed += obj => { tcs.SetResult(null); };
return ((Task) tcs.Task).GetAwaiter();
}
}
public class HttpManager
{
///
/// 异步Get
///
///
/// 数据获取之后执行的回调
///
internal async void GetAsync(string uri, Action 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(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(webRequest.downloadHandler.text);
var t = typeof(T) == typeof(MNull) ? default : JsonConvert.DeserializeObject(handle.data.ToString());
toDo?.Invoke(t, handle);
}
catch (Exception e)
{
Debug.Log("e : " + e);
}
break;
}
}
///
/// 异步获取图片
///
/// 地址
/// 传进来的图片尺寸
/// 把sprite和Texture2D一起返回方便管理(在使用后销毁)
internal async void GetImg(string uri, Vector2Int size, Action 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;
}
}
///
/// 异步Post
///
/// 地址
/// 表单
/// 头
/// 数据上传之后执行的回调
///
internal async void PostAsync(string uri, WWWForm form, Dictionary header = null, Action 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(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(webRequest.downloadHandler.text);
var t = typeof(T) == typeof(MNull) ? default : JsonConvert.DeserializeObject(handle.data.ToString());
toDo?.Invoke(t, handle);
}
catch (Exception e)
{
Debug.LogError("e : " + e);
}
break;
}
}
}
这样就可以了。