我正在尝试从 Unity 平台在 Windows Phone 8 上执行发布请求。我不想使用统一的 WWW 方法,因为这会阻止渲染(并且不是线程安全的)。
以下代码可以在编辑器和 Android 上运行,但是在为 WP8 构建它时出现以下错误。
System.Byte[] System.Net.WebClient::UploadData(System.String,System.String,System.Byte[])` 在目标框架中不存在。
这个错误的原因解释在这里
这是因为 Windows Phone 8 使用一种不同风格的 .NET,称为 .NET for Windows Phone,它缺少其他平台上可用的一些类型。您必须用不同的类型替换这些类型或自己实现它们。 - http://docs.unity3d.com/Manual/wp8-faq.html
这是我的代码
using (WebClient client = new WebClient())
{
client.Encoding = System.Text.Encoding.UTF8;
client.Headers[HttpRequestHeader.ContentType] = "application/json";
byte[] requestData = new byte[0];
string jsonRequest = "{}";
if (data != null)
{
string tempRequest = Converter.SerializeToString (data);
jsonRequest = "{\"Data\": \"" + tempRequest + "\"}";
requestData = System.Text.Encoding.UTF8.GetBytes(jsonRequest);
}
// below line of code is the culprit
byte[] returnedData = client.UploadData(url, "POST", requestData);
if(returnedData.Length > 0)
{
// do stuff
}
}
我也尝试过WebRequests,但是GetResponse()破坏了它,并且HttpClient不存在。
那么,如何在 Windows Phone 8 上在 Unity 中发布数据,而不使用 WWW?
根据评论请求更新 - WebRequests
此代码使用 HttpWebRequest 在编辑器和 Android 上运行,但在 Windows Phone 上会引发代码下面列出的错误。
var request = (System.Net.HttpWebRequest) System.Net.WebRequest.Create(url);
request.ContentType = "application/json";
request.Method = "POST";
var sw = new System.IO.StreamWriter(request.GetRequestStream(), System.Text.Encoding.UTF8);
sw.Write(jsonRequest); // jsonRequest is same variable as in above code, string with json object.
sw.Close();
var re = request.GetResponse();
string resultString = "";
using (var outputStream = new System.IO.StreamReader(re.GetResponseStream(), System.Text.Encoding.UTF8))
{
resultString = outputStream.ReadToEnd();
}
if(resultString.Length > 0)
{}
错误1:
错误:目标框架中不存在方法
。System.IO.Stream System.Net.HttpWebRequest::GetRequestStream()
错误2:
目标框架中不存在。System.Net.WebResponse System.Net.HttpWebRequest::GetResponse()
更新更多细节 - UploadStringAsync
使用此代码发出异步请求,它在编辑器中再次运行良好,但在 WP8 上会引发错误。
bool isCompleted = false;
byte[] returnedData = null;
client.UploadDataCompleted +=
new UploadDataCompletedEventHandler((object sender, UploadDataCompletedEventArgs e) =>
{
Debug.Log("return event");
returnedData = e.Result;
isCompleted =true;
});
Debug.Log("async call start");
client.UploadDataAsync(new Uri(url), requestData);
while(isCompleted == false){
Thread.Sleep(100);
}
if(returnedData.Length > 0)
{}
错误1
方法
在目标框架中不存在。System.Void System.Net.WebClient::add_UploadDataCompleted(System.Net.UploadDataCompletedEventHandler)
错误2
错误:目标框架中不存在方法
。System.Void System.Net.WebClient::UploadDataAsync(System.Uri,System.Byte[])
错误3
错误:目标框架中不存在类型
。System.Net.UploadDataCompletedEventArgs
错误4
错误:目标框架中不存在方法
。System.Byte[] System.Net.UploadDataCompletedEventArgs::get_Result()
我不知道 Unity 对您施加的任何潜在限制,但 Windows Phone 8 有
WebClient.UploadStringAsync
方法 和 WebClient.UploadStringCompleted
事件 来执行此操作。
HttpWebRequest
也应该可以工作(同样,我不知道任何 Unity 限制 - 请参阅上面的评论以获取澄清)。
使用下面的代码在 Windows Phone 上使用它。在 Android 和 WP8 上的编辑器中编译并运行(耶!)。 iOS 上还没试过。
还在这里写了一篇关于它的文章:创建适用于所有平台(甚至是 WP8)的统一 Web 请求
/// <summary>
/// Make post request to url with given paramaters
/// </summary>
/// <param name="url">URL to post data to http://server.com/method </param>
/// <param name="data">{ Data: data }</param>
/// <returns>string server response</returns>
public string PostData(string url, string data)
{
// json request, hard coded right now but use "data" paramater to set this value.
string jsonRequest = "{\"Data\": \"data\"}"; // the json request
var request = System.Net.WebRequest.Create(url) as System.Net.HttpWebRequest;
// this could be different for your server
request.ContentType = "application/json";
// i want to do post and not get
request.Method = "POST";
// used to check if async call is complete
bool isRequestCallComplete = false;
// store the response in this
string responseString = string.Empty;
request.BeginGetRequestStream(ar =>
{
var requestStream = request.EndGetRequestStream(ar);
using (var sw = new System.IO.StreamWriter(requestStream))
{
// write the request data to the server
sw.Write(jsonRequest);
// force write of all content
sw.Flush();
}
request.BeginGetResponse(a =>
{
var response = request.EndGetResponse(a);
var responseStream = response.GetResponseStream();
using (var sr = new System.IO.StreamReader(responseStream))
{
// read in the servers response right here.
responseString = sr.ReadToEnd();
}
// set this to true so the while loop at the end stops looping.
isRequestCallComplete = true;
}, null);
}, null);
// wait for request to complete before continuing
// probably want to add some sort of time out to this
// so that the request is stopped after X seconds.
while (isRequestCallComplete == false) { Thread.Sleep(50); }
return responseString;
}
您无法从 Unity 中使用这些框架,因为它们是线程/异步/使用另一个版本的 .Net
简而言之:
要在 Windows Phone 上执行此操作,您需要创建一个类库(实际上是两个),Unity 称之为插件
那么为什么有两个 dll?
因为编辑器需要一个模型 dll(如果您也想在桌面上实现它,则需要实际的 dll),该模型实现与 Windows Phone 上兼容的 dll 相同的接口。
要明确:
所以你应该在dll中实现该功能,然后统一引用它,最后直接调用它。
所有内容都在这里解释:http://docs.unity3d.com/Manual/wp8-plugins-guide-csharp.html
它比看起来更简单。
我知道你说过你不想使用 WWW 类,但你给出的理由在我看来没有意义。
如果您使用协程检查“.isDone”标志,而不是使用 Thread.Sleep() 检查它,它不会阻止渲染并且是线程安全的(因为 Unity 只允许您在单个线程上访问其信息)。
如果您想访问另一个线程上的返回数据,您只需在主统一线程中读取该数据,然后将其传递到您想要使用它的任何线程。
Unity 的设计全部在单个线程上运行,以使经验不足的程序员的工作更轻松。 虽然您应该能够使用 .NET 线程创建多个线程,但您将无法直接与任何 Unity 组件通信,但您可以将数据传递回 Unity 并等待 Update 或 Unity 的其他调用来使用数据。我知道这并不能完全回答您的问题,但如果您无法解决它,我认为值得再次查看 WWW 类以及使用它的最佳实践。