Version: 6000.3
语言: 中文
创建 UploadHandlers
在运行时向对象添加功能

创建 DownloadHandlers

有几种类型DownloadHandlers:

  • DownloadHandlerBuffer用于简单的数据存储。
  • DownloadHandlerFile用于以低内存占用下载文件并将其保存到磁盘。
  • DownloadHandlerTexture用于下载图像。
  • DownloadHandlerAssetBundle用于获取资产包。
  • DownloadHandlerAudioClip用于下载音频文件。
  • DownloadHandlerMovieTexture用于下载视频文件。建议使用 VideoPlayer 进行视频下载和电影播放,因为 MovieTexture 已弃用。
  • DownloadHandlerScript是一个特殊的班级。它本身什么也没做。但是,此类可以由用户定义的类继承。此类从 UnityWebRequest 系统接收回调,然后可用于在数据从网络到达时对其执行完全自定义的处理。

API 类似于DownloadHandlerTexture的界面。

UnityWebRequest有一个属性disposeDownloadHandlerOnDispose,默认为 true。如果此属性为 true,则在释放 UnityWebRequest 对象时,还将在附加的下载处理程序上调用 Dispose(),使其无用。如果保留对下载处理程序的引用的时间长于对 UnityWebRequest 的引用,则应将 disposeDownloadHandlerOnDispose 设置为 false。

下载处理程序缓冲区

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

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;
        }
    }
}

下载处理程序文件

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

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);
    }
}

下载处理程序纹理

而不是使用DownloadHandlerBuffer下载图像文件,然后使用Texture.LoadImage,使用起来效率更高DownloadHandlerTexture.

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

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

以下示例从 Internet 下载 PNG 文件,将其转换为精灵A 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;
        }
    }
}

下载处理程序资产包

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

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

AssetBundle 通过DownloadHandlerAssetBundle对象,它有一个特殊的assetBundle属性来检索 AssetBundle。

由于 AssetBundle 系统的工作方式,所有 AssetBundle 都必须有一个与之关联的地址。通常,这是它们所在的名义 URL(即任何重定向之前的 URL)。在几乎所有情况下,您都应传入与传递给 UnityWebRequest 相同的 URL。使用高级 API (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;
        }
    }
}

下载处理程序音频剪辑

此下载处理程序针对下载音频文件进行了优化。而不是使用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
        }
    }
}

下载处理程序脚本

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

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

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

要覆盖的函数

接收内容长度()

protected void ReceiveContentLength(long contentLength);

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

OnContentComplete()

protected void OnContentComplete();

当 UnityWebRequest 从服务器完全下载所有数据,并将所有接收到的数据转发到 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
在运行时向对象添加功能