在Unity中调用后端接口

概述

        在Unity中我们常常需要后端提供的接口,这是一种网络请求,增删改查数据库中的数据,而Unity为我们提供了一个强大的类:UnityWebRequest来帮助我们.

世界观

        但在讲这个类之前我们需要掌握一些基本知识,才能更好的理解我们到底在干什么.也就说我先简单讲一下后端在干什么,然后再讲使用Unity和后端对接.

        现在数据一般是放在数据库中的,使用SQL语句可以查询数据库,但是现代开发往往是模块化开发,降低耦合,所以又实现了一个中间层来对接数据库(譬如C#使用asp.net core ,java使用spring),Unity其实是通过Http协议和这个中间层打交道,Unity调用中间层提供的接口,中间层再去调用数据库(当然这也涉及了很多技术,但不是我们讨论的重点),这样Unity最终接触的是一个个接口,只要调用这个接口就可以实现对数据的增删改查,大大简化了彼此的依赖.现在我们以接口为切入点向下展开.

URL 和 Uri 的区别和联系

接口,其实就是一个个url或者uri.

1 URL(统一资源定位符:Uniform Resource Locator):

是一种具体的 Uri,它不仅标识资源,还包含访问该资源的方法(如 http://example.com)。

URL 包含协议(如 http、https)、域名、路径、查询参数等。

 

2 Uri(统一资源标识符:Uniform Resource Identifier):

是一个更广泛的概念,用于标识任何资源。Uri 可以是 URL,也可以是 URN(统一资源名称)。

Uri 通常由协议、主机、路径、查询和片段组成。

 

在UnityWebRequest中使用两者(往往两者就是该类的构造函数的参数)

URL:

URL 是一个字符串,代表目标资源的地址。可以是 web 地址(如 http://example.com)或本地文件路径(如 file://path/to/file)。

Uri:

Uri 是一个类,代表一个统一资源标识符,可以包含更详细的结构化信息。

可以通过构造函数或静态方法来创建 Uri 对象。

        一般来说url更简单(因为就是一个地址字符串),但是uri和url差别并不是太大,往往后端会给你提供一个个url,可以直接使用.

HTTP协议:

        HTTP 是一个应用层协议,主要用于传输超文本(如 HTML),但也可以传输图片、视频、JSON(在Unity中我们往往使用的是json) 数据等。HTTP 协议运行在 TCP/IP 之上,确保数据传输的可靠性。客户端和服务端往往都是通过请求响应式方式进行交互(譬如使用浏览器,输入一个网址进行请求,服务器接受到后解析然后返回内容).

HTTP 请求和响应

HTTP 请求:

由客户端(如浏览器或应用程序)发送到服务器,包含请求行、请求头和请求体。

请求行包括 HTTP 方法(如 GET、POST)、请求的 URL 和 HTTP 版本。

 

HTTP 响应: 

由服务器返回给客户端,包含状态行、响应头和响应体。

状态行包括 HTTP 版本、状态码(如 200、404)和状态描述。

 

HTTP 请求和响应的详细组成(选读)

HTTP 请求

HTTP 请求是由客户端发送到服务器的消息,它由三个主要部分组成:请求行、请求头和请求体。

1请求行 (Request Line):

HTTP 方法: 指定要对资源执行的操作(例如 GET、POST、PUT、DELETE)。

请求的 URL: 资源的路径,通常包括路径和查询参数。

HTTP 版本: 指定使用的 HTTP 协议版本(例如 HTTP/1.1)。

示例:

GET /index.html HTTP/1.1

 

2请求头 (Request Headers):

包含关于客户端环境、请求体内容以及其他元数据的信息。

常见的请求头包括:

Host: 服务器的主机名和端口号。

User-Agent: 客户端的软件信息(例如浏览器类型和版本)。

Accept: 客户端希望接收的响应内容类型。

Content-Type: 请求体的媒体类型(用于 POST 或 PUT 请求)。

Authorization: 用于认证的凭证信息。

示例:

Host: www.example.com

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

3请求体 (Request Body):

包含需要发送到服务器的数据。GET 请求通常没有请求体,而 POST 和 PUT 请求则通常包含请求体。

请求体的数据格式通常由 Content-Type 头指定(例如 application/json, application/x-www-form-urlencoded)。

示例:

{

    "name": "John Doe",

    "age": 30

}

 

HTTP 响应

HTTP 响应是服务器返回给客户端的消息,它也由三个主要部分组成:状态行、响应头和响应体。

1状态行 (Status Line):

HTTP 版本: 指定使用的 HTTP 协议版本(例如 HTTP/1.1)。

状态码: 指示请求的处理结果(例如 200, 404, 500)。

状态描述: 对状态码的简短描述(例如 OK, Not Found, Internal Server Error)。

示例:

HTTP/1.1 200 OK

2响应头 (Response Headers):

包含关于服务器、响应体内容以及其他元数据的信息。

常见的响应头包括:

Content-Type: 响应体的媒体类型。

Content-Length: 响应体的字节长度。

Date: 服务器生成响应的日期和时间。

Server: 服务器的软件信息。

Set-Cookie: 服务器发送的 Cookie 信息。

示例:

Content-Type: text/html; charset=UTF-8

Content-Length: 1234

Date: Mon, 31 May 2024 12:34:56 GMT

Server: Apache/2.4.41 (Ubuntu)

3响应体 (Response Body):

包含服务器返回给客户端的实际数据。可以是 HTML、JSON、XML、图片、视频等。

响应体的数据格式通常由 Content-Type 头指定。

示例:

 

<!DOCTYPE html>

<html>

<head>

    <title>Example</title>

</head>

<body>

    <h1>Hello, world!</h1>

</body>

</html>

三 完整示例:完整的 HTTP 请求和响应

HTTP 请求示例

一个典型的 GET 请求可能如下所示:

GET /index.html HTTP/1.1

Host: www.example.com

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Language: en-US,en;q=0.5

Accept-Encoding: gzip, deflate

Connection: keep-alive

HTTP 响应示例

服务器的响应可能如下所示:

 

HTTP/1.1 200 OK

Content-Type: text/html; charset=UTF-8

Content-Length: 138

Date: Mon, 31 May 2024 12:34:56 GMT

Server: Apache/2.4.41 (Ubuntu)

 

<!DOCTYPE html>

<html>

<head>

    <title>Example</title>

</head>

<body>

    <h1>Hello, world!</h1>

</body>

</html>

        我们平常使用浏览器,输入一个网址并不接触这些东西,但是这些过程的确发生了,并不会显示给用户看(没有这个必要).下面我们简单剖析这个过程:

        在浏览器中输入一个地址并按下回车时,发生了一系列的过程。这个过程中,浏览器会构造一个HTTP请求发送到服务器。我们可以通过分析一个具体的URL来说明这一过程:

假设输入了:https://www.example.com/products?category=books&price=low

分析这个地址:

协议:https

这表明使用的是HTTPS协议,即HTTP的安全版本,数据传输会进行加密。

域名:www.example.com

这是服务器的地址,浏览器通过这个域名找到相应的服务器。

路径:/products

这指明了在服务器上资源的具体位置,通常对应服务器上的一个文件夹或由服务器动态生成的内容。

查询字符串:category=books&price=low

这部分包含了要传送给服务器的额外数据,用于告诉服务器用户想要查看哪种类别的产品,以及产品的价格范围是如何的。

构造的HTTP请求:

当输入并提交这个URL后,浏览器会发送一个HTTP GET请求到服务器。这个请求可能看起来如下:

请求行:

GET /products?category=books&price=low HTTP/1.1

请求头:

Host: www.example.com

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/58.0.3029.110 Safari/537.36

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

Accept-Language: en-US,en;q=0.5

Connection: keep-alive

在这个例子中:

请求行明确了使用的方法(GET),请求的资源(包括路径和查询字符串),以及HTTP协议的版本。

请求头包含了服务器需要的或对请求处理有帮助的附加信息,如哪种浏览器正在发起请求,客户端可以接收哪些类型的数据,以及连接类型等。

通过这个例子可以看到,即使是简单地在浏览器中输入一个地址,背后也有一系列复杂的步骤和数据交换过程,以确保可以查看请求的网页。

 

总结

请求行和状态行:分别包含请求的基本信息和响应的基本信息。

请求头和响应头:包含元数据,描述请求和响应的细节。

请求体和响应体:包含实际的数据内容,根据请求或响应的类型不同而变化。

常见的 HTTP 方法

HTTP 方法(也称为动词)定义了客户端希望对资源执行的操作。笔者所应用的场景多数都是和后端交换一些json,所以多数使用GET和POST,这也是最常用的两种.以下是几种常见的 HTTP 方法:

GET:

用于从服务器请求资源。GET 请求应该是幂等的(对同一资源的多次请求不会产生不同的效果)。

POST:

用于向服务器提交数据,通常用于表单提交或上传文件。POST 请求可以改变服务器上的资源状态。

PUT:

用于更新服务器上的资源,通常是替换资源的全部内容。PUT 请求应该是幂等的。

DELETE:

用于删除服务器上的资源。DELETE 请求应该是幂等的。

HEAD:

与 GET 类似,但服务器只返回响应头,不返回响应体。通常用于检查资源的元数据(如大小、类型)。

OPTIONS:

用于获取服务器支持的 HTTP 方法和其他通信选项。

方法论

UnityWebRequest 的不同构造函数及其使用示例:

 

1. 使用默认构造函数

UnityWebRequest request = new UnityWebRequest();

2. 使用 URL 作为字符串

string url = "http://example.com";

UnityWebRequest request = new UnityWebRequest(url);

3. 使用 Uri 对象

Uri uri = new Uri("http://example.com");

UnityWebRequest request = new UnityWebRequest(uri);

4. 使用 Uri 对象和 HTTP 方法

Uri uri = new Uri("http://example.com");

UnityWebRequest request = new UnityWebRequest(uri, "POST");

5. 使用 Uri 对象、HTTP 方法、下载处理器和上传处理器

Uri uri = new Uri("http://example.com");

DownloadHandler downloadHandler = new DownloadHandlerBuffer();

UploadHandler uploadHandler = new UploadHandlerRaw(new byte[] { });

 

UnityWebRequest request = new UnityWebRequest(uri, "POST", downloadHandler, uploadHandler);

总结

URL 是 Uri 的一种特定形式,包含访问资源的方法。

Uri 是一个更广泛的标识符,可以表示任何资源。

UnityWebRequest 的构造函数可以接受 URL 字符串或 Uri 对象来指定请求目标。

在选择构造函数时,可以根据需要选择合适的参数类型和数量。

UnityWebRequest 作用

UnityWebRequest 作为一个工具,用于在 Unity 中实现和使用 HTTP 协议。HTTP(HyperText Transfer Protocol,超文本传输协议)是用于在万维网(WWW)上进行数据通信的协议。它是一种无状态、面向连接的协议,基于请求-响应模式。

使用 UnityWebRequest 执行上述 HTTP 方法的示例:

GET 请求

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;

public class GetRequestExample : MonoBehaviour
{
    private void Start()
    {
        StartCoroutine(GetRequest("https://jsonplaceholder.typicode.com/posts/1"));
    }

    IEnumerator GetRequest(string uri)
    {
    //这里使用静态Get方法快速生成了一个可以发生GET请求的UnityWebRequest实例
        using (UnityWebRequest webRequest = UnityWebRequest.Get(uri))
        {	//发送网络请求,使用协程等待该异步操作
            yield return webRequest.SendWebRequest();
            if (webRequest.result == UnityWebRequest.Result.Success)            
 				Debug.Log(webRequest.downloadHandler.text);
            else Debug.LogError(webRequest.error);
 }    
    }/*为什么使用协程呢?因为网络请求要花费较长的时间,
    协程的异步操作可以避免卡死主线程
    为什么使用using?因为先使用Get方法
    生成了一个可以发生网络请求的UnityWebRequest 实例,
    这是一个需要被释放的资源,使用using可以优雅的
    在花括号结尾自动释放资源,不需要显示释放,当然也可以
    不使用using,那么需要显示调用Dispose释放资源*/
}

UnityWebRequest.Result 枚举值

讲一下出现的这个枚举值,这个是较新版本的判断方式

InProgress

表示请求仍在进行中。通常在开始请求后到请求完成前的这段时间内会出现这个状态。

Success

表示请求成功完成,没有发生错误,服务器返回了有效的响应。

ConnectionError

表示请求过程中发生了连接错误,通常是因为网络问题或无法与服务器建立连接。

ProtocolError

表示请求成功发送到服务器,但服务器返回了错误响应,例如 404 Not Found 或 500 Internal Server Error。

DataProcessingError

表示请求完成,但在处理服务器返回的数据时发生了错误,例如无法解析 JSON 响应。

POST 请求

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
using System.Text;

public class PostRequestExample : MonoBehaviour
{
    private void Start()
    {
        StartCoroutine(PostRequest("https://jsonplaceholder.typicode.com/posts", "        
        {\"title\":\"foo\",\"body\":\"bar\",\"userId\":1}"));
        //与GET不同,这里上传了一个json给后端使用
    }

    IEnumerator PostRequest(string uri, string jsonData)
    {
        var request = new UnityWebRequest(uri, "POST");//构造POST对象
        byte[] bodyRaw = Encoding.UTF8.GetBytes(jsonData);//将json数据转为二进制
        //这里讲下updownloadHandler属性,UnityWebRequest实例管理着
        //该属性和downloadHandler属性,这两个属性来进行上传和下载数据
        //使用低级方法配置UnityWebRequest实例需要自己对这两个属性赋值
        request.uploadHandler = new UploadHandlerRaw(bodyRaw);
        request.downloadHandler = new DownloadHandlerBuffer();
        //发生请求头,这里只处理了媒体类型Content-Type,设置为application/json
        request.SetRequestHeader("Content-Type", "application/json");
        /*这里和GET还有很大不同,上面直接调用一个Get()的静态方法返回一个可以直接使用的对象,
        这里我将其称为一种高级方法,就是Unity官方进行了封装,而POST例子中这样,
        自己配置各种属性,这里称为低级方法,低级方法相对高级方法有更大的自由度,
        开发者可以掌握更多的细节,当然POST对应的高级方法就是.POST()方法*/
        yield return request.SendWebRequest();
        /*注意,这里就是发生网络请求,在发生网络求请后不允许对UnityWebRequest再进行配置,
        也就是说所有的配置都需要在发送请求之前.*/

        if (request.result == UnityWebRequest.Result.ConnectionError || request.result ==     UnityWebRequest.Result.ProtocolError)
        {
            Debug.LogError(request.error);
        }
        else
        {
            Debug.Log(request.downloadHandler.text);
        }
    }
}

总结

HTTP 协议 是一种应用层协议,用于在客户端和服务器之间传输数据。

HTTP 方法 定义了对资源的操作,如 GET、POST、PUT、DELETE 等。

UnityWebRequest 实现了 HTTP 协议,提供了发送和处理 HTTP 请求的功能。

Content-Type

        这里还要再讲解一下HTTP中请求头的Content-Type,主要是在POST或者PUT中应用,因为GET不需要请求头,GET仅请求数据并不提交数据或者仅在请求行提供简单数据(且是以明文形式),举个例子用户登录需要输入账号密码,这通常需要被设计成一个POST请求,除了请求地址我们还要加上信息发送给后端,我们需要和后端约定使用什么格式的媒体类型,方便后端解析.

 

下面深入介绍下媒体类型

        在HTTP请求中,Content-Type 是一个非常重要的HTTP头部(header),它告诉服务器发送的数据是什么格式。通过这个头部,服务器可以理解如何解析接收到的数据内容。Content-Type头部的主要功能是指明HTTP消息体中内容的类型。这是通过指定MIME类型来实现的,MIME类型通常包含两部分:一种类型和一个子类型,用斜线/分隔。例如,在application/json中,application是类型,json是子类型。

 

1. Content-Type 的定义

Content-Type 是一个标准的HTTP头部,用于定义HTTP请求或响应中的媒体类型(即数据格式)。这个头部告诉服务器和客户端实体体(entity body)的媒体类型是什么。例如,当您向服务器发送数据时,Content-Type 告诉服务器怎样解析这些数据。

2. 常见的媒体类型

application/json:表示发送或接收的内容格式是JSON(JavaScript Object Notation)。JSON是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。

application/xml 或 text/xml:

用途:用于传输XML格式的数据。虽然JSON在Web应用中更常用,XML仍广泛用于支持遗留系统的接口或特定的行业标准。

text/html:表示HTML格式,通常在浏览器中请求网页时使用。

application/x-www-form-urlencoded:通常在提交HTML表单时使用。表单数据会编码为键值对,类似于URL查询字符串。

multipart/form-data:一种用于HTML表单的编码类型,允许上传文件。

text/plain:纯文本格式,没有特定格式。

3. 在UnityWebRequest中设置Content-Type

        当使用 UnityWebRequest 创建请求时,尤其是在发送POST或PUT请求时(这些请求通常会包含数据),正确设置Content-Type是非常重要的,因为它决定了数据如何被服务器解释。以下是设置 Content-Type 的代码示例:

 

using (UnityWebRequest request = new UnityWebRequest(url, "POST"))

{

    string jsonData = JsonConvert.SerializeObject(someObject);

    byte[] bodyRaw = Encoding.UTF8.GetBytes(jsonData);

    request.uploadHandler = new UploadHandlerRaw(bodyRaw);

    request.downloadHandler = new DownloadHandlerBuffer();

    request.SetRequestHeader("Content-Type", "application/json");

}

  1. 为什么选择 application/json,

选择 application/json 作为 Content-Type:

 

通用性:JSON格式在现代网络应用中广泛使用,特别是在REST API中,因为它提供了一个简洁且高效的方式来交换数据。

易于处理:大多数编程语言都有解析和生成JSON数据的库,如JavaScript, Python, C#, Java等。

结构化数据:JSON支持复杂的数据结构,如嵌套对象和数组,这对于表达复杂的数据非常有用。

通过设置 Content-Type 为 application/json,确保数据以JSON格式发送,并且期望服务器按JSON格式处理接收到的数据。这样的明确声明有助于避免数据解析错误和相关的问题。

        具体选择什么类型需要和后端约定,application/x-www-form-urlencoded也是十分常用的格式,且如果直接使用静态Post方法构造一个实例,不显式配置格式默认就是使用application/x-www-form-urlencoded,且在Unity中存在WWWForm类帮我们轻松处理信息而不需要我们关注细节.

        选择合适的Content-Type取决于想如何格式化数据以及接收方预期如何处理这些数据。选择正确的Content-Type可以确保数据正确地被接收和解析,从而避免数据格式错误、解析错误和相关的通信问题。

  1. 使用SetRequestHeader设置任何有效的HTTP头部

        SetRequestHeader方法允许你自定义请求的HTTP头部信息。这些头部信息用于向服务器提供额外的指令或信息,如内容类型、认证信息、接受类型等。

 

常见的HTTP请求头部

Content-Type:

描述了请求正文的媒体类型(MIME类型),如application/json、multipart/form-data等。

Authorization:

用于支持HTTP认证机制,如Bearer tokens、Basic Auth等。

示例:request.SetRequestHeader("Authorization", "Bearer your_access_token_here");

User-Agent:

标识发出请求的浏览器或其他客户端应用的类型和版本。

示例:request.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");

Accept:

指定客户端能够接收的内容类型,如application/json、text/html等。

示例:request.SetRequestHeader("Accept", "application/json");

Cookie:

发送存储在用户本地的Cookie到服务器。

示例:request.SetRequestHeader("Cookie", "username=JohnDoe");

Referer:

表示请求发起源的地址,有时用于防止 CSRF 攻击或日志记录。

示例:request.SetRequestHeader("Referer", "http://example.com");

设置多个HTTP头部的示例:

 

using UnityEngine.Networking;

UnityWebRequest request = new UnityWebRequest("http://example.com/api/data", "POST");

// 设置Content-Type头部

request.SetRequestHeader("Content-Type", "application/json");

// 设置Authorization头部

request.SetRequestHeader("Authorization", "Bearer your_access_token_here");

// 设置Accept头部

request.SetRequestHeader("Accept", "application/json");

// 确保添加对应的上传和下载处理器

request.uploadHandler = new UploadHandlerRaw(bodyRaw);

request.downloadHandler = new DownloadHandlerBuffer();

request.SetRequestHeader是一个灵活的方法,允许根据需求设置各种HTTP头部。这些头部信息对于控制HTTP请求和响应的处理具有重要作用.

封装GET方法和POST方法

        这里我使用了协程封装,但是使用协程有好有坏,好处是Unity官方实现,集成好并且简单,缺点是一切异步只能在内部处理,不能像使用async和await一样有返回值,不能使用try/catch,所以这里传递一个委托来回调处理返回结果,这样提高了阅读成本

        public IEnumerator PostRequestAboutJsonCoroutine(string uri, Action<string> 
          callback, WWWForm formData, int timeout = 0)
        {
            var getWebRequest = UnityWebRequest.Post(uri, formData);
            getWebRequest.timeout = timeout;
            yield return getWebRequest.SendWebRequest();
#if UNITY_2020_1_OR_NEWER
            if (getWebRequest.result == UnityWebRequest.Result.Success)
            {
#else
        if (!unityWebRequest.isNetworkError && !unityWebRequest.isHttpError)
            {
#endif
                if (!getWebRequest.downloadHandler.text.IsNullOrEmpty())
                    callback(getWebRequest.downloadHandler.text);
                else
                    Debug.Log("json error");
            }
        }
        public IEnumerator GetRequestAboutJsonCoroutine(string uri, Action<string>         
        callback, int timeout = 0)
        {
            var getWebRequest = UnityWebRequest.Get(uri);
            getWebRequest.timeout = timeout;
            yield return getWebRequest.SendWebRequest();
#if UNITY_2020_1_OR_NEWER
            if (getWebRequest.result == UnityWebRequest.Result.Success)
            {
#else
        if (!unityWebRequest.isNetworkError && !unityWebRequest.isHttpError)
            {
#endif
                if (!getWebRequest.downloadHandler.text.IsNullOrEmpty())
                    callback(getWebRequest.downloadHandler.text); 
                else
                    Debug.Log("json error");
            }
        }

        所以我这里提供一个使用UniTask库来处理网络请求并将GET和POST都集成到该方法中,第二个参数建议使用UnityWebRequest.kHttpVerbGET或kHttpVerbPOST避免出错

        public async UniTask<T> WebRequestAboutJsonAsync<T>(string uri, string type, int     
           timeout = 0,WWWForm formData = null)
        {
            UnityWebRequest unityWebRequest = new UnityWebRequest(uri);
            unityWebRequest.method = type.ToString();
            var cts = new CancellationTokenSource();
            cts.CancelAfterSlim(TimeSpan.FromSeconds(timeout));
            try
            {
                switch (type)
                {
                    case UnityWebRequest.kHttpVerbGET:
                    return await WebRequestAboutJsonBaseAsync<T>(unityWebRequest, cts);
                    case UnityWebRequest.kHttpVerbPOST:
                        if (formData != null)
                        {
                            var bodyRaw = formData.data;
                            unityWebRequest.uploadHandler = newUploadHandlerRaw(bodyRaw);
                            foreach (var header in formData.headers)
                            {    
                             unityWebRequest.SetRequestHeader(header.Key,header.Value);
                            }

                            //unityWebRequest.SetRequestHeader("Content-Type",         
                            //"application/x-www-form-urlencoded");
                       return await WebRequestAboutJsonBaseAsync<T>(unityWebRequest,cts);
                        }
                        else
                        {
                            Debug.LogError($"<color=red><b><size=15>未传入有效的POST对象</size></b></color>");
                            return default(T);
                        }
                    default:
                        return default(T);
                }
            }
            catch (OperationCanceledException ex)
            {
                if (ex.CancellationToken == cts.Token)
                {
                    Debug.Log($"<color=red><b><size=15>Timeout</size></b></color>"); 
                    //这里有点奇怪,使用.Error会卡死程序
                }

                return default(T);
            }
            catch (System.Exception e)
            {
                Debug.LogError($"<color=red><b><size=15>{e.Message}</size></b></color>");
                return default(T);
            }
            finally
            {
                unityWebRequest.Dispose();
                cts.Dispose();
            }
        }

        private async UniTask<T> WebRequestAboutJsonBaseAsync<T>(UnityWebRequest     
        unityWebRequest,CancellationTokenSource cts)
        {
            unityWebRequest.downloadHandler = new DownloadHandlerBuffer();

            await unityWebRequest.SendWebRequest().WithCancellation(cts.Token);
#if UNITY_2020_1_OR_NEWER
            if (unityWebRequest.result == UnityWebRequest.Result.Success)
            {
#else
        if (!unityWebRequest.isNetworkError && !unityWebRequest.isHttpError)
            {
#endif

                string responseText = unityWebRequest.downloadHandler.text;
                return JsonConvert.DeserializeObject<T>(responseText);
            }
            else
            {
                Debug.LogError("网络错误: " + unityWebRequest.error);
                return default(T);
            }
        }

 

 

  • 26
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity调用摄像头需要使用WebCamTexture类。以下是调用摄像头的步骤: 1. 在Unity创建一个空物体,将其命名为“CameraController”。 2. 在“CameraController”物体上添加一个脚本,例如“WebCamController”。 3. 在“WebCamController”脚本添加以下代码: ``` using UnityEngine; using System.Collections; public class WebCamController : MonoBehaviour { // 定义一个WebCamTexture对象 WebCamTexture webcamTexture; // Use this for initialization void Start () { // 获取摄像头设备 WebCamDevice[] devices = WebCamTexture.devices; if (devices.Length > 0) { // 获取第一个摄像头设备 webcamTexture = new WebCamTexture(devices[0].name); // 将摄像头纹理赋值给当前对象的渲染器 GetComponent<Renderer>().material.mainTexture = webcamTexture; // 开始捕捉摄像头 webcamTexture.Play(); } } } ``` 此代码会从设备获取第一个摄像头设备,并将其赋值给WebCamTexture对象。然后将WebCamTexture对象的纹理赋值给当前对象的渲染器,最后开始捕捉摄像头。 4. 将“CameraController”物体拖入场景,运行游戏即可看到摄像头捕捉到的图像。 注意:在使用摄像头时需要获取用户的授权。可以使用Application.RequestUserAuthorization方法来请求授权。例如: ``` void Start () { // 请求用户授权 if (Application.HasUserAuthorization(UserAuthorization.WebCam)) { // 获取摄像头设备... } else { Application.RequestUserAuthorization(UserAuthorization.WebCam); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值