Version: 5.4 beta (switch to 5.3)
Networking Tips for Mobile devices.
Networking Reference

UnityWebRequest

The UnityWebRequest is a replacement for Unity’s original WWW object. It provides a modular system for composing HTTP requests and handling HTTP responses. The primary goal of the UnityWebRequest system is to permit Unity games to interact with modern Web backends. It also supports high-demand features such as chunked HTTP requests, streaming POST/PUT operations and full control over HTTP headers and verbs.

For end-users who only employ common WWW use cases, transitioning to the new system should be almost a find-and-replace process.

The system consists of two layers. A Low-Level API (LLAPI) provides maximum flexibility for power users, while a High-Level API (HLAPI) wraps the Low-Level API and provides a convenient interface for performing common operations.

Supported Platforms

The UnityWebRequest system supports most Unity platforms.

Platforms supported in 5.2:

  • All versions of the Editor & Standalone players
  • WebGL

Platforms supported in 5.3:

  • Mobile Platforms: iOS, Android, Windows Phone 8
  • Windows Store Apps

Additional platform support will be rolled out in further 5.x releases:

  • PS4, PS Vita, and PS Mobile
  • XBox 360 and XBox One
  • Wii U

Architecture

The UnityWebRequest ecosystem breaks down an HTTP transaction into three distinct operations:

  • Supplying data to the server
  • Receiving data from the server
  • HTTP flow control (redirects, error handling, etc.)

To provide a better interface for power users, these operations are each governed by their own objects:

  • An UploadHandler object handles transmission of data to the server
  • A DownloadHandler object handles receipt, buffering and postprocessing of data received from the server
  • A UnityWebRequest object, which manages the other two objects, and also handles HTTP flow control. This object is where custom headers and URLs are defined, and where error and redirect information is stored.

For any given HTTP transaction, the generic code flow is:

  • Create a Web Request object
  • Configure the Web Request object
    • Set custom headers
    • Set HTTP verb (GET, POST, HEAD, etc.)
      • Custom verbs are permitted
    • Set URL
  • (Optional) Create an Upload Handler & attach it to the Web Request
    • Provide data to be uploaded
    • Provide HTTP form to be uploaded
  • (Optional) Create a Download Handler & attach it to the Web Request
  • Send the Web Request
    • If inside a coroutine, you may Yield the result of the Send() call to wait for the request to complete, just like WWW.
  • (Optional) Read received data from the Download Handler
  • (Optional) Read error information, HTTP status code and response headers from the UnityWebRequest object

Common Operations: Using the HLAPI

This section details the options available in the High-Level API, and the scenarios they are intended to address.

Retrieve Text or Binary Data from an HTTP Server (GET)

To retrieve simple data, such as textual data or binary data, from a standard HTTP or HTTPS web server, the call to use is UnityWebRequest.GET. This method takes a single string as an argument; the string specifies the URL from which data will be retrieved.

This method is analogous to the standard WWW constructor:

WWW myWww = new WWW("http://www.myserver.com/foo.txt");
// ... is analogous to ...
UnityWebRequest myWr = UnityWebRequest.Get("http://www.myserver.com/foo.txt");

Details:

This method creates a UnityWebRequest and sets the target URL to the string argument. It sets no other custom flags or headers.

By default, this method attaches a standard DownloadHandlerBuffer to the UnityWebRequest. This handler will buffer the data received from the server and make it available to your scripts when the request is complete.

By default, this method attaches no UploadHandler to the UnityWebRequest. You may attach one manually if you wish.

Example:

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
 
class MyBehaviour: public MonoBehaviour {
    void Start() {
        StartCoroutine(GetText());
    }
 
    IEnumerator GetText() {
        UnityWebRequest www = UnityWebRequest.Get("http://www.my-server.com");
        yield return www.Send();
 
        if(www.isError) {
            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;
        }
    }
}

Retrieve a Texture from an HTTP Server (GET)

To retrieve a texture file from a remote server, you may use UnityWebRequest.Texture. This method is very similar to UnityWebRequest.GET, but is optimized for downloading and storing textures efficiently.

This method takes a single string as an argument. The string specifies the URL from which you wish to download an image file for use as a texture.

Details:

This method creates a UnityWebRequest and sets the target URL to the string argument. This method sets no other flags or custom headers.

This method attaches a DownloadHandlerTexture object to the UnityWebRequest. DownloadHandlerTexture is a specialized Download Handler which is optimized for storing images which are to be used as textures in the Unity Engine. Using this class significantly reduces memory reallocation compared to downloading raw bytes and creating a texture manually in script.

By default, this method attaches on Upload Handler. You may add one manually if you wish.

Example:

using UnityEngine;
using System.Collections;
 
class MyBehaviour: public MonoBehaviour {
    void Start() {
        StartCoroutine(GetTexture());
    }
 
    IEnumerator GetTexture() {
        UnityWebRequest www = UnityWebRequest.GetTexture("http://www.my-server.com/image.png");
        yield return www.Send();

        if(www.isError) {
            Debug.Log(www.error);
        }
        else {
            Texture myTexture = ((DownloadHandlerTexture)www.downloadHandler).texture;
        }
    }
}

Alternatively, you can implement GetTexture using a helper getter:
    IEnumerator GetTexture() {
        UnityWebRequest www = UnityWebRequest.GetTexture("http://www.my-server.com/image.png");
        yield return www.Send();

        Texture myTexture = DownloadHandlerTexture.GetContent(www);
    }

Downloading an Asset Bundle from an HTTP Server (GET)

To retrieve an asset bundle from a remote server, you may use UnityWebRequest.AssetBundle. This method streams data into an internal buffer, which decodes/decompresses the asset bundle’s data on a worker thread.

The method’s arguments take several forms. In its simplest form, it takes only the URL from which the asset bundle should be downloaded. You may optionally provide a checksum to verify the integrity of the downloaded data.

Alternately, if you wish to use the asset bundle caching system, you may provide either a version number or a Hash128 data structure. These are identical to the version numbers or Hash128 objects provided to the old system via WWW.LoadFromCacheOrDownload.

Details:

This method creates a UnityWebRequest and sets the target URL to the supplied URL argument. It also sets the HTTP verb to GET, but sets no other flags or custom headers.

This method attaches a DownloadHandlerAssetBundle to the UnityWebRequest. This download handler has a special assetBundle property, which can be used to extract the asset bundle once enough data has been downloaded and decoded to permit access to the resources inside the bundle.

If you supply a version number or Hash128 object as arguments, it also passes those arguments to the DownloadHandlerAssetBundle. The download handler will then employ the caching system.

Example:

using UnityEngine;
using System.Collections;
 
class MyBehaviour: public MonoBehaviour {
    void Start() {
        StartCoroutine(GetAssetBundle());
    }
 
    IEnumerator GetAssetBundle() {
        UnityWebRequest www = UnityWebRequest.GetAssetBundle("http://www.my-server.com/myData.unity3d");
        yield return www.Send();
 
        if(www.isError) {
            Debug.Log(www.error);
        }
        else {
            AssetBundle bundle = ((DownloadHandlerAssetBundle)www.downloadHandler).assetBundle;
        }
    }
}

Alternatively, you can implement GetAssetBundle using a helper getter:

    IEnumerator GetTexture() {
        UnityWebRequest www = UnityWebRequest.GetAssetBundle("http://www.my-server.com/myData.unity3d");
        yield return www.Send();

        AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(www);
    }

Sending a Form to an HTTP Server (POST)

There are two primary methods for sending data to a server, formatted as an HTML Form.

Legacy Method: Using WWWForm

To help migrate from the old WWW system, the new UnityWebRequest system permits you to use the old WWWForm object to provide form data.

In this case, the function signature is:

WebRequest.Post(string url, WWWForm formData);
Details:

This method creates a new UnityWebRequest and sets the target URL to the first string argument’s value. It also reads any custom headers generated by the WWWForm argument (such as Content-Type) and copies them into the UnityWebRequest.

This method, by default, attaches a DownloadHandlerBuffer to the UnityWebRequest. This is for convenience: you can use this to check your server’s replies.

This method reads the raw data generated by the WWWForm object and buffers it in an UploadHandlerRaw object, which is attached to the UnityWebRequest. Therefore, changes to the WWWFormobject after calling UnityWebRequest.POST will not alter the contents of the UnityWebRequest.

Example:

using UnityEngine;
using System.Collections;
 
class MyBehavior: public MonoBehaviour {
    void Start() {
        StartCoroutine(Upload());
    }
 
    IEnumerator Upload() {
        WWWForm form = new WWWForm();
        form.AddField("myField", "myData");
 
        UnityWebRequest www = UnityWebRequest.Post("http://www.my-server.com/myform", form);
        yield return www.Send();
 
        if(www.isError) {
            Debug.Log(www.error);
        }
        else {
            Debug.Log("Form upload complete!");
        }
    }
}

New Method: Using IMultipartFormSection

To provide greater control over how you specify your form data, the UnityWebRequestsystem contains a (user-implementable) IMultipartFormSection interface. For standard applications, Unity also provides default implementations for data and file sections: MultipartFormDataSection and MultipartFormFileSection.

An overload of UnityWebRequest.POST accepts, as a second parameter, a List argument, whose members must all be IMultipartFormSections. The function signature is:

WebRequest.Post(string url, List<IMultipartFormSection> formSections);
Details:

This method creates a UnityWebRequest and sets the target URL to the first string parameter. It also sets the Content-Type header of the UnityWebRequest appropriately for the form data specified in the list of IMultipartFormSection objects.

This method, by default, attaches a DownloadHandlerBuffer to the UnityWebRequest. This is for convenience: you can use this to check your server’s replies.

Similar to the WWWForm POST method, this HLAPI method will call each supplied IMultipartFormSection in turn and format them into a standard multipart form as specified in RFC 2616.

The preformatted form data will be stored in a standard UploadHandlerRaw object, which is then attached to the UnityWebRequest. As a result, changes to the IMultipartFormSection objects performed after the UnityWebRequest.POST call will not be reflected in the data sent to the server.

Example:

using UnityEngine;
using System.Collections;
 
class MyBehavior: public MonoBehaviour {
    void Start() {
        StartCoroutine(Upload());
    }
 
    IEnumerator Upload() {
        List<IMultipartFormSection> formData = new List<IMultipartFormSection>();
        formData.Add( new MultipartFormDataSection("field1=foo&field2=bar") );
        formData.Add( new MultipartFormFileSection("my file data", "myfile.txt") );

        UnityWebRequest www = UnityWebRequest.Post("http://www.my-server.com/myform", formData);
        yield return www.Send();
 
        if(www.isError) {
            Debug.Log(www.error);
        }
        else {
            Debug.Log("Form upload complete!");
        }
    }
}

Uploading Raw Data to an HTTP Server (PUT)

Some modern web applications prefer that files be uploaded via the HTTP PUT verb. For this scenario, Unity provides the UnityWebRequest.PUT method.

This method takes two arguments. The first argument is a string and specifies the target URL for the request. The second argument may be either a string or a byte array, and specifies the payload data to be sent to the server.

Function signatures:

WebRequest.Put(string url, string data);
WebRequest.Put(string url, byte[] data);

Details:

This method creates aUnityWebRequest and sets the content type to application/octet-stream.

This method attaches a standard DownloadHandlerBuffer to the UnityWebRequest. As with the POST methods, you can use this to return result data from your applications.

This method stores the input upload data in a standard UploadHandlerRaw object and attaches it to the UnityWebRequest. As a result, if using the byte[] method, changes to the byte array performed after the UnityWebRequest.PUT call will not be reflected in the uploaded data to the server.

Example:

using UnityEngine;
using System.Collections;
 
class MyBehavior: public MonoBehaviour {
    void Start() {
        StartCoroutine(Upload());
    }
 
    IEnumerator Upload() {
        byte[] myData = System.Text.Encoding.UTF8.GetBytes("This is some test data");
        UnityWebRequest www = UnityWebRequest.Put("http://www.my-server.com/upload", myData);
        yield return www.Send();
 
        if(www.isError) {
            Debug.Log(www.error);
        }
        else {
            Debug.Log("Upload complete!");
        }
    }
}

Finer Control: Using the LLAPI

While the HLAPI is designed to minimize boilerplate code, the LLAPI is designed to permit maximum flexibility. In general, using the LLAPI involves creating UnityWebRequests, then creating appropriate DownloadHandlers or UploadHandlers and attaching them to your UnityWebRequests.

For full details on each of the objects described in this section, please refer to the Scripting Reference.

Note: The HLAPI and LLAPI are not mutually exclusive. You can always customize UnityWebRequest objects created via the HLAPI if you need to tweak a common scenario.

Creating UnityWebRequests

WebRequests can be simply instantiated like any other object. Two constructors are available. The standard, parameterless constructor creates a new UnityWebRequest with all settings blank or default: * The target URL is not set * No custom headers are set * The redirect limit is set to 32

The second constructor takes a string argument. It assigns the UnityWebRequest’s target URL to the value of the string argument, and is otherwise identical to the parameterless constructor.

Example:

UnityWebRequest wr = new UnityWebRequest(); // Completely blank
UnityWebRequest wr2 = new UnityWebRequest("http://www.mysite.com"); // Target URL is set

Creating UploadHandlers

Currently, only one type of upload handler is available: UploadHandlerRaw. This class accepts a data buffer at construction time. This buffer is copied internally into native-code memory and then used by the UnityWebRequest system when the remote server is ready to accept body data.

Upload Handlers also accept a Content Type string. This string will be used for the value of the UnityWebRequest’s Content-Type header if you set no Content-Type header on the UnityWebRequest itself. If you manually set a Content-Type header on the UnityWebRequest object, then the Content-Type on the Upload Handler object will be ignored.

If you do not set a Content-Type on either the UnityWebRequest or the UploadHandler, then the system will default to setting a Content-Type of application/octet-stream.

Example:

byte[] payload = new byte[1024];
// ... fill payload with data ...

UnityWebRequest wr = new UnityWebRequest("http://www.mysite.com/data-upload");
UploadHandler uploader = new UploadHandlerRaw(payload);

// Will send header: "Content-Type: custom/content-type";
uploader.contentType = "custom/content-type";

wr.uploadHandler = uploader;

Creating DownloadHandlers

Currently, there are four types of DownloadHandlers:

  • DownloadHandlerBuffer stores received data in a native-code byte buffer, and permits access either to the raw bytes or will convert it into a UTF8 string.
  • DownloadHandlerTexture stores received data in a UnityEngine.Texture. On download completion, it will decode JPEGs and PNGs into valid UnityEngine.Texture objects. Only one copy of the UnityEngine.Texture will be created per DownloadHandlerTexture object, which will reduce performance hits from garbage collection.
  • DownloadHandlerAssetBundle streams received data into Unity’s asset bundle system. Once the asset bundle system has received enough data, the asset bundle will be available as a UnityEngine.AssetBundle object. As above, only one copy of the UnityEngine.AssetBundle object will be created to reduce memory impact.
  • DownloadHandlerScript is a special class. On its own, it will do nothing. However, this class can be inherited by a user-defined class. This class will receive callbacks from the UnityWebRequest system, which can then be used to perform completely custom handling of data as it arrives from the network.

A specialized Download Handler for Audio Clips is also available. The APIs are analogous to DownloadHandlerTexture’s interface.

Simple Data Storage: DownloadHandlerBuffer

This download handler is the simplest and handles the majority of use cases. It simply stores received data in a (native-code) buffer. When the download is complete, you may access the buffered data either as an array of bytes or as a UTF8 string.

Example:
using UnityEngine;
using System.Collections;
 
class MyBehaviour: public MonoBehaviour {
    void Start() {
        StartCoroutine(GetText());
    }
 
    IEnumerator GetText() {
        UnityWebRequest www = new UnityWebRequest("http://www.my-server.com");
        www.downloadHandler = new DownloadHandlerBuffer();
        yield return www.Send();
 
        if(www.isError) {
            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;
        }
    }
}

Downloading Pictures: DownloadHandlerTexture

While you could use a DownloadHandlerBuffer to download an image file and then create a texture from the raw bytes using Texture.LoadImage, it’s more efficient to use DownloadHandlerTexture.

This download handler performs buffering, decompression and texture creation in native code. Further, decompression and texture creation are performed on a worker thread instead of the main thread, which can improve frame time when loading large textures.

Finally, DownloadHandlerTexture only allocates managed memory when finally creating the Texture itself, which eliminates the garbage collection overhead associated with performing the byte-to-texture conversion in script.

The following example downloads a PNG from the internet, converts it to a Sprite and assigns it to a uGUI Image:

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
[RequireComponent(typeof(UnityEngine.UI.Image))]
public class ImageDownloader : MonoBehaviour {
    UnityEngine.UI.Image _img;
 
    void Start () {
        _img = GetComponent<UnityEngine.UI.Image>();
        Download("http://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.Send();
        if(!wr.isError) {
            Texture2D t = texDl.texture;
            Sprite s = Sprite.Create(t, new Rect(0, 0, t.width, t.height),
                                     Vector2.zero, 1f);
            _img.sprite = s;
        }
    }
}

Fetching Asset Bundles: DownloadHandlerAssetBundle

The advantage to this specialized download handler is that it is capable of streaming data to Unity’s asset bundle system. This considerably reduces runtime memory allocation, as well as the memory impact of loading your asset bundles. Further, it allows asset bundles to be partially used while not fully downloaded - that is, you can stream assets.

All downloading and decompression occurs on worker threads.

Asset Bundles are downloaded via a DownloadHandlerAssetBundle object, which has a special assetBundle property to retrieve the asset bundle. Due to the way the Asset Bundle system works, all asset bundles must have an address associated with them. Generally, this is the nominal URL at which they’re located (i.e. the URL prior to redirects). In almost all cases, you should simply pass in the same URL as you passed to the UnityWebRequest. When using the HLAPI, this is done for you.

Example:

using UnityEngine;
using System.Collections;
 
class MyBehaviour: public MonoBehaviour {
    void Start() {
        StartCoroutine(GetAssetBundle());
    }
 
    IEnumerator GetAssetBundle() {
        UnityWebRequest www = new UnityWebRequest("http://www.my-server.com");
        DownloadHandlerAssetBundle handler = new DownloadHandlerAssetBundle(www.url);
        www.downloadHandler = handler;
        yield return www.Send();
 
        if(www.isError) {
            Debug.Log(www.error);
        }
        else {
            // Extracts asset bundle
            AssetBundle bundle = handler.assetBundle;
        }
    }
}

Do It Yourself: DownloadHandlerScript

For power users who require full control over the processing of downloaded data, Unity provides the DownloadHandlerScript class.

By default, instances of this class will do nothing. However, if you derive your own classes from DownloadHandlerScript, you may override certain methods and use them to receive callbacks as data arrives from the network.

Note: Even though the actual downloads occur on a worker thread, all DownloadHandlerScript callbacks operate on the main thread. Avoid performing computationally-heavy operations during these callbacks.

Methods to Override
protected void ReceiveContentLength(long contentLength);

This method is called when the Content-Length header is received.

Note: This callback may occur multiple times if your server issues one or more redirect responses over the course of processing your UnityWebRequest.

protected void OnContentComplete();

This method is called when the UnityWebRequest has fully downloaded all data from the server, and has forwarded all received data to the ReceiveData callback.

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

This method is called after data has arrived from the remote server. This method will be called once per frame. The data argument contains the raw bytes received from the remote server, and dataLength indicates the length of new data in the data array.

When not using pre-allocated data buffers, the system will create a new byte array each time it calls this callback, and dataLength will always be equal to data.Length. When using pre-allocated data buffers, the data buffer will be reused and dataLength must be used to find the number of updated bytes.

This method requires a return value of either true or false. If you return false, the system will immediately abort the UnityWebRequest. If you return true, processing will continue normally.

For more on preallocated data buffers, see the following subsection.
Avoiding GC Overhead: DownloadHandlerScripts with pre-allocated buffers

Many of Unity’s power users are constantly concerned with reducing CPU spikes due to garbage collection. For these users, the UnityWebRequest system permits the pre-allocation of a managed-code byte array which will be used to deliver downloaded data to DownloadHandlerScript’s ReceiveData callback.

Using this method completely eliminates managed-code memory allocation when using DownloadHandlerScript-derived classes to capture downloaded data.

To make a DownloadHandlerScript operate with a pre-allocated managed buffer, simply supply a byte array to the constructor of DownloadHandlerScript.

Note: The size of the byte array limits the amount of data delivered to the ReceiveData callback each frame. Do not provide too small of a byte array or your data will arrive slowly, over many frames.

Example

using UnityEngine;
using System.Collections;

public class LoggingDownloadHandler : DownloadHandlerScript {

    // Standard scripted download handler - will allocate memory on each ReceiveData callback
    public LoggingDownloadHandler(): base() {
    }

    // Pre-allocated scripted download handler
    // Will reuse 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 ReceiveContentLength(int contentLength) {
        Debug.Log(string.Format("LoggingDownloadHandler :: ReceiveContentLength - length {0}", contentLength));
    }
}
Networking Tips for Mobile devices.
Networking Reference