版本:Unity 6 (6000.0)
语言:英语
创建 UploadHandlers
在运行时向对象添加功能

创建 DownloadHandlers

有几种类型的 DownloadHandlers

  • DownloadHandlerBuffer 用于简单的數據存儲。
  • DownloadHandlerFile 用于将文件下载并保存到磁盘,内存占用量低。
  • DownloadHandlerTexture 用于下载图像。
  • DownloadHandlerAssetBundle 用于获取 AssetBundles。
  • DownloadHandlerAudioClip 用于下载音频文件。
  • DownloadHandlerMovieTexture 用于下载视频文件。建议使用 VideoPlayer 进行视频下载和电影播放,因为 MovieTexture 已被弃用。
  • DownloadHandlerScript 是一个特殊的类。它本身不执行任何操作。但是,此类可以被用户定义的类继承。此类接收来自 UnityWebRequest 系统的回调,这些回调可用于在数据从网络到达时执行完全自定义的数据处理。

API 与 DownloadHandlerTexture 的接口类似。

UnityWebRequest 具有一个属性 disposeDownloadHandlerOnDispose,默认值为 true。如果此属性为 true,当 UnityWebRequest 对象被处置时,Dispose() 也将在附加的下载处理程序上调用,使其失效。如果您对下载处理程序的引用时间比对 UnityWebRequest 的引用时间长,则应将 disposeDownloadHandlerOnDispose 设置为 false。

DownloadHandlerBuffer

此下载处理程序是最简单的,并且处理大多数用例。它将接收到的数据存储在本地代码缓冲区中。下载完成后,您可以将缓冲数据作为字节数组或文本字符串访问。

示例

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


public class MyBehaviour : MonoBehaviour {
    void Start() {
        StartCoroutine(GetText());
    }

    IEnumerator GetText() {
        UnityWebRequest www = new UnityWebRequest("https://www.my-server.com");
        www.downloadHandler = new DownloadHandlerBuffer();
        yield return www.SendWebRequest();

        if (www.result != UnityWebRequest.Result.Success) {
            Debug.Log(www.error);
        }
        else {
            // Show results as text
            Debug.Log(www.downloadHandler.text);

            // Or retrieve results as binary data
            byte[] results = www.downloadHandler.data;
        }
    }
}

DownloadHandlerFile

这是一个用于大型文件的特殊下载处理程序。它将下载的字节直接写入文件,因此无论下载的文件大小如何,内存使用量都保持较低。与其他下载处理程序的区别在于,您无法从此下载处理程序中获取数据,所有数据都保存到文件中。

示例

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

public class FileDownloader : MonoBehaviour {

    void Start () {
        StartCoroutine(DownloadFile());
    }

    IEnumerator DownloadFile() {
        var uwr = new UnityWebRequest("https://unity3d.com/", UnityWebRequest.kHttpVerbGET);
        string path = Path.Combine(Application.persistentDataPath, "unity3d.html");
        uwr.downloadHandler = new DownloadHandlerFile(path);
        yield return uwr.SendWebRequest();
        if (uwr.result != UnityWebRequest.Result.Success)
            Debug.LogError(uwr.error);
        else
            Debug.Log("File successfully downloaded and saved to " + path);
    }
}

DownloadHandlerTexture

与使用 DownloadHandlerBuffer 下载图像文件,然后使用 Texture.LoadImage 从原始字节创建纹理相比,使用 DownloadHandlerTexture 更有效率。

此下载处理程序将接收到的数据存储在 UnityEngine.Texture 中。下载完成后,它将 JPEG 和 PNG 解码为有效的 UnityEngine.Texture 对象。每个 DownloadHandlerTexture 对象只创建一个 UnityEngine.Texture 的副本。这减少了垃圾回收的性能损失。处理程序在本地代码中执行缓冲、解压缩和纹理创建。此外,解压缩和纹理创建是在工作线程而不是主线程上执行的,这可以提高加载大型纹理时的帧时间。

最后,DownloadHandlerTexture 仅在最终创建 Texture 本身时才分配托管内存,这消除了在脚本中执行字节到纹理转换时与垃圾回收相关的开销。

示例

以下示例从互联网下载一个 PNG 文件,将其转换为 精灵2D 图形对象。如果您习惯于在 3D 中工作,精灵本质上只是标准纹理,但存在用于组合和管理精灵纹理的特殊技术,以提高开发过程中的效率和便捷性。 更多信息
词汇表
,并将其分配给 图像

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

[RequireComponent(typeof(Image))]
public class ImageDownloader : MonoBehaviour {
    Image _img;

    void Start () {
        _img = GetComponent<UnityEngine.UI.Image>();
        Download("https://www.mysite.com/myimage.png");
    }

    public void Download(string url) {
        StartCoroutine(LoadFromWeb(url));
    }

    IEnumerator LoadFromWeb(string url)
    {
        UnityWebRequest wr = new UnityWebRequest(url);
        DownloadHandlerTexture texDl = new DownloadHandlerTexture(true);
        wr.downloadHandler = texDl;
        yield return wr.SendWebRequest();
        if (wr.result == UnityWebRequest.Result.Success) {
            Texture2D t = texDl.texture;
            Sprite s = Sprite.Create(t, new Rect(0, 0, t.width, t.height),
                Vector2.zero, 1f);
            _img.sprite = s;
        }
    }
}

DownloadHandlerAssetBundle

此专用下载处理程序的优势在于,它能够将数据流式传输到 Unity 的 AssetBundle 系统。一旦 AssetBundle 系统接收了足够的数据,AssetBundle 就可以作为 UnityEngine.AssetBundle 对象使用。只创建一个 UnityEngine.AssetBundle 对象的副本。这大大减少了运行时内存分配,以及加载 AssetBundle 的内存影响。它还允许在未完全下载的情况下部分使用 AssetBundles,因此您可以流式传输 Assets。

所有下载和解压缩都在工作线程上进行。

AssetBundles 通过 DownloadHandlerAssetBundle 对象下载,该对象具有一个特殊的 assetBundle 属性来检索 AssetBundle。

由于 AssetBundle 系统的工作方式,所有 AssetBundle 都必须与它们关联一个地址。通常,这是它们所在的标称 URL(即重定向之前的 URL)。在几乎所有情况下,您应该传递与传递给 UnityWebRequest 相同的 URL。当使用 高级 API用于构建 Unity 游戏多人功能的系统。它建立在低级传输实时通信层之上,并处理多人游戏所需的许多常见任务。 更多信息
词汇表
(HLAPI) 时,将为您完成此操作。

示例

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

public class MyBehaviour : MonoBehaviour {
    void Start() {
        StartCoroutine(GetAssetBundle());
    }

    IEnumerator GetAssetBundle() {
        UnityWebRequest www = new UnityWebRequest("https://www.my-server.com");
        DownloadHandlerAssetBundle handler = new DownloadHandlerAssetBundle(www.url, uint.MaxValue);
        www.downloadHandler = handler;
        yield return www.SendWebRequest();

        if (www.result != UnityWebRequest.Result.Success) {
            Debug.Log(www.error);
        }
        else {
            // Extracts AssetBundle
            AssetBundle bundle = handler.assetBundle;
        }
    }
}

DownloadHandlerAudioClip

此下载处理程序针对下载音频文件进行了优化。与使用 DownloadHandlerBuffer 下载原始字节,然后从中创建 AudioClip 相比,您可以使用此下载处理程序以更便捷的方式进行操作。

示例

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

public class AudioDownloader : MonoBehaviour {

    void Start () {
        StartCoroutine(GetAudioClip());
    }

    IEnumerator GetAudioClip() {
        using (var uwr = UnityWebRequestMultimedia.GetAudioClip("https://myserver.com/mysound.ogg", AudioType.OGGVORBIS)) {
            yield return uwr.SendWebRequest();
            if (uwr.result != UnityWebRequest.Result.Success) {
                Debug.LogError(uwr.error);
                yield break;
            }

            AudioClip clip = DownloadHandlerAudioClip.GetContent(uwr);
            // use audio clip
        }
    }
}

DownloadHandlerScript

对于需要完全控制下载数据处理的用户,Unity 提供了 DownloadHandlerScript 类。

默认情况下,此类的实例不执行任何操作。但是,如果您从 DownloadHandlerScript 派生自己的类,则可以覆盖某些函数,并使用它们在数据从网络到达时接收回调。

注意:实际下载是在工作线程上进行的,但所有 DownloadHandlerScript 回调都在主线程上运行。在这些回调期间,避免执行计算量大的操作。

要覆盖的函数

ReceiveContentLength()

protected void ReceiveContentLength(long contentLength);

当接收到 Content-Length 标头时,会调用此函数。请注意,如果您的服务器在处理 UnityWebRequest 的过程中发送一个或多个重定向响应,则此回调可能会多次发生。

OnContentComplete()

protected void OnContentComplete();

当 UnityWebRequest 已从服务器完全下载所有数据,并将所有接收到的数据转发到 ReceiveData 回调时,会调用此函数。

ReceiveData()

protected bool ReceiveData(byte[] data, long dataLength);

当数据从远程服务器到达后,会调用此函数,并且每帧调用一次。data 参数包含从远程服务器接收到的原始字节,dataLength 指示数据数组中新数据的长度。

当不使用预分配的数据缓冲区时,系统会在每次调用此回调时创建一个新的字节数组,并且 dataLength 始终等于 data.Length。当使用预分配的数据缓冲区时,数据缓冲区将被重用,并且必须使用 dataLength 来查找更新的字节数。

此函数需要一个返回值,可以是 truefalse。如果您返回 false,系统将立即中止 UnityWebRequest。如果您返回 true,处理将照常继续。

避免垃圾回收开销

许多 Unity 的高级用户都关心减少因垃圾回收引起的 CPU 尖峰。对于这些用户,UnityWebRequest 系统允许预分配一个托管代码字节数组,该数组用于将下载的数据传递到 DownloadHandlerScript 的 ReceiveData 回调。

使用此函数完全消除了使用 DownloadHandlerScript 派生类捕获下载数据时的托管代码内存分配。

为了使 DownloadHandlerScript 与预分配的托管缓冲区一起操作,请向 DownloadHandlerScript 的构造函数提供一个字节数组。

注意:字节数组的大小限制了每帧传递到 ReceiveData 回调的数据量。如果您的数据缓慢到达,跨越许多帧,那么您可能提供的字节数组太小了。

示例

using UnityEngine;
using UnityEngine.Networking;

public class LoggingDownloadHandler : DownloadHandlerScript {

    // Standard scripted download handler - allocates memory on each ReceiveData callback

    public LoggingDownloadHandler(): base() {
    }

    // Pre-allocated scripted download handler
    // reuses the supplied byte array to deliver data.
    // Eliminates memory allocation.

    public LoggingDownloadHandler(byte[] buffer): base(buffer) {
    }

    // Required by DownloadHandler base class. Called when you address the 'bytes' property.

    protected override byte[] GetData() { return null; }

    // Called once per frame when data has been received from the network.

    protected override bool ReceiveData(byte[] data, int dataLength) {
        if(data == null || data.Length < 1) {
            Debug.Log("LoggingDownloadHandler :: ReceiveData - received a null/empty buffer");
            return false;
        }

        Debug.Log(string.Format("LoggingDownloadHandler :: ReceiveData - received {0} bytes", dataLength));
        return true;
    }

    // Called when all data has been received from the server and delivered via ReceiveData.

    protected override void CompleteContent() {
        Debug.Log("LoggingDownloadHandler :: CompleteContent - DOWNLOAD COMPLETE!");
    }

    // Called when a Content-Length header is received from the server.

    protected override void ReceiveContentLengthHeader(ulong contentLength) {
        Debug.Log(string.Format("LoggingDownloadHandler :: ReceiveContentLength - length {0}", contentLength));
    }
}
创建 UploadHandlers
在运行时向对象添加功能