28 人が閲覧(直近 30 日) シミュレーション

UnityWebRequestの使い方|GET・POST(JSON)・timeout・エラー処理とawait【Unity 6対応】

UnityWebRequestの使い方|GET・POST(JSON)・timeout・エラー処理とawait【Unity 6対応】

UnityWebRequestは、UnityでHTTP通信をするための標準クラスです(名前空間はUnityEngine.Networking)。この記事では、GETでデータを取る・POSTでJSONを送る・timeoutを設定する・resultで失敗を見分ける、という実装に必要な手順を、Unity 6向けのサンプルコードで説明します。2017〜2018年の解説に残るisNetworkErrorやPost(url, json)が、現行版で何に変わったかも示します。Unity 6系そのものの変更点はUnity 6.3 LTS(6000.3)の新機能と変更点|最新パッチ・サポート期限・6.0からの移行にまとめています。

まとめ

  • 流れは「生成→SendWebRequest()で送信→resultで判定→usingで破棄」の4手順。GETはUnityWebRequest.Get(url)。
  • JSONのPOSTは、Unity 2022.2以降ならUnityWebRequest.Post(url, json, "application/json")。引数2つのPost(url, json)は文字列をURLエンコードしてフォーム形式で送るため、JSON APIには届かない。
  • timeoutはint型の秒数で、既定値0は「時間制限なし」。送信後に設定すると例外になるので、SendWebRequest()の前に入れる。
  • 判定はrequest.resultの5値で行う。isNetworkError・isHttpErrorはObsolete。再試行は一時的な失敗(接続断・408・429・500・502・503・504など)に絞り、API仕様と冪等性で最終判断する。
  • Unity 2023.1以降(Unity 6を含む)はawait request.SendWebRequest()と書ける。
  • 通信できないときは、HTTP接続の禁止(Unity 2022.1以降の既定)とWebGLでのCORSを確認する。資源管理ではDisposeを忘れない。旧WWWクラスはUnity 6でもObsoleteのまま残っている。

UnityWebRequestの基本:生成・送信・判定・破棄の4手順

UnityWebRequestを使うには、スクリプトの先頭にusing UnityEngine.Networking;を書きます。どの通信も、次の4手順で書けます。

  1. UnityWebRequest.Get(url)などの静的メソッドでリクエストを作る
  2. SendWebRequest()で送信し、コルーチンならyield return、async関数ならawaitで完了を待つ
  3. request.resultで成否を判定し、本文をrequest.downloadHandler.textで読む
  4. usingで囲んで破棄する(成功・失敗どちらでもDisposeが必要)

作成用のメソッドは用途ごとに分かれています。

用途 作成メソッド 受信側
取得 UnityWebRequest.Get(url) DownloadHandlerBuffer
JSON送信 UnityWebRequest.Post(url, json, contentType) DownloadHandlerBuffer
フォーム送信 UnityWebRequest.Post(url, WWWForm) DownloadHandlerBuffer
更新・削除 Put(url, body) / Delete(url) Deleteは受信側なし
画像 UnityWebRequestTexture.GetTexture(url) DownloadHandlerTexture
音声 UnityWebRequestMultimedia.GetAudioClip(url, AudioType) DownloadHandlerAudioClip
AssetBundle UnityWebRequestAssetBundle.GetAssetBundle(url) DownloadHandlerAssetBundle

new UnityWebRequest(url, "PATCH")のようにコンストラクターで任意のメソッド名を渡すこともできます。この場合はuploadHandlerとdownloadHandlerを自分で付けます。

GETでのデータ取得:コルーチンの実装例

MonoBehaviourのStartをコルーチン(IEnumerator)にすると、そのままyield returnで送信完了を待てます。次のコードは、取得に成功したら本文を表示し、HTTPエラーと通信エラーを分けてログに出します。

この記事のサンプルは、UnityCsReference(6000.6.0f1)のAPIシグネチャに対して型が合うことを確認したもので、Unityエディタでの通信動作は確認していません。https://example.com/...は仮のURLなので、自分のAPIのURLに置き換えてください。クラス全体を載せていない断片は、MonoBehaviourを継承したクラスの中に置き、IEnumeratorのメソッドとしてStartCoroutineで呼び出します。

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

public class GetSample : MonoBehaviour
{
    IEnumerator Start()
    {
        using (UnityWebRequest request = UnityWebRequest.Get("https://example.com/api/score"))
        {
            request.timeout = 10; // 送信前に設定する(秒)
            yield return request.SendWebRequest();

            switch (request.result)
            {
                case UnityWebRequest.Result.Success:
                    Debug.Log(request.downloadHandler.text);
                    break;
                case UnityWebRequest.Result.ProtocolError: // 404や500など
                    Debug.LogWarning($"HTTP {request.responseCode}: {request.downloadHandler.text}");
                    break;
                default: // ConnectionError / DataProcessingError
                    Debug.LogError($"{request.result}: {request.error}");
                    break;
            }
        }
    }
}

受け取ったJSONをC#のクラスに変換するにはJsonUtility.FromJson<T>(request.downloadHandler.text)を使います。変換先のクラスには[System.Serializable]を付け、フィールドはpublicにします(次章のScoreResponseを参照)。JSONシリアライズのマニュアルのとおり、JsonUtilityはDictionaryに対応せず、配列やプリミティブ型を直接渡すこともできません。APIが配列を返すときは{"items":[...]}の形にラップしてから変換するか、Newtonsoft.Jsonなど別のJSONライブラリを使います。

URLのクエリに日本語や記号を入れるときは、UnityWebRequest.EscapeURL("Fish & Chips")でエスケープしてから連結します。

POSTでのデータ送信:JSON・フォーム・2022.1以前の書き方

JSONの送信:Post(url, json, “application/json”)

Unity 2022.2で、Content-Typeを第3引数に取るUnityWebRequest.Postのオーバーロードが追加されました。文字列はUTF-8のバイト列としてUploadHandlerRawに入り、受信用のDownloadHandlerBufferも自動で付きます。Unity 6でJSONを送るなら、この書き方が最短です。

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

[System.Serializable]
public class ScoreRequest { public string userId; public int score; }

[System.Serializable]
public class ScoreResponse { public int rank; public string message; }

public class PostJsonSample : MonoBehaviour
{
    IEnumerator Start()
    {
        string json = JsonUtility.ToJson(new ScoreRequest { userId = "u001", score = 1200 });

        // Unity 2022.2以降:第3引数でContent-Typeを指定する
        using (UnityWebRequest request = UnityWebRequest.Post("https://example.com/api/score", json, "application/json"))
        {
            request.timeout = 10;
            yield return request.SendWebRequest();

            if (request.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError($"{request.responseCode} {request.error}");
                yield break;
            }
            ScoreResponse res = JsonUtility.FromJson<ScoreResponse>(request.downloadHandler.text);
            Debug.Log($"rank={res.rank}");
        }
    }
}

Post(url, json)ではJSONが届かない理由

引数2つのPost(string uri, string postData)は、Unity 2022.2以降Obsoleteです。UnityCsReferenceのソース(6000.6.0f1)を読むと、このメソッドはpostDataをWWWTranscoder.WwwFormEncodeでURLエンコードし、Content-Typeをapplication/x-www-form-urlencodedにして送ります。そのため{"score":1200}は%7B%22score%22...のような文字列になり、JSONを期待するサーバーは解釈できません。後からSetRequestHeader("Content-Type", "application/json")を足しても、本文はエンコード済みのままです。

コンパイラ警告のメッセージは「Content-Type引数付きのPostかPostWwwFormを使え」で、自動更新(UnityUpgradable)の置換先はPostWwwFormになっています。API Updaterに任せると、JSONを送っていた箇所もフォーム送信のままになります。JSON APIを呼んでいる箇所は、手でContent-Type付きのPostに書き換えてください。

Unity 2022.1以前のJSON送信:UploadHandlerRaw

2022.1以前のプロジェクトでは、new UnityWebRequest(url, "POST")にハンドラーを自分で付けます。

IEnumerator PostJson(string url, string json)
{
    byte[] body = System.Text.Encoding.UTF8.GetBytes(json);
    using (UnityWebRequest request = new UnityWebRequest(url, "POST"))
    {
        request.uploadHandler = new UploadHandlerRaw(body);
        request.downloadHandler = new DownloadHandlerBuffer(); // 付けないとレスポンス本文を読めない
        request.SetRequestHeader("Content-Type", "application/json");
        yield return request.SendWebRequest();
        Debug.Log($"{request.responseCode} {request.error}"); // resultは2020.1以降
    }
}

コンストラクターで作ったリクエストにはdownloadHandlerが付きません。付け忘れると、送信は成功してもrequest.downloadHandlerがnullでレスポンス本文を読めません。

フォームの送信:WWWFormとPostWwwForm

HTMLフォームと同じ形式で送るときはWWWFormを使います。画像などのファイルを添付する場合はform.AddBinaryData(フィールド名, バイト列, ファイル名, MIMEタイプ)を使います。MIMEタイプを省略すると、先頭8バイトがPNGの形式ならimage/png、それ以外はapplication/octet-streamとして送られます。

WWWForm form = new WWWForm();
form.AddField("name", "player1");
form.AddField("score", 1200);

using (UnityWebRequest request = UnityWebRequest.Post("https://example.com/form", form))
{
    yield return request.SendWebRequest();
    Debug.Log(request.result);
}

すでにname=player1&score=1200の形の文字列を持っているなら、UnityWebRequest.PostWwwForm(url, "name=player1&score=1200")でも送れます。

リクエストヘッダーの設定とレスポンスヘッダーの取得

リクエストヘッダーはSetRequestHeader(名前, 値)で付けます。認証トークンはAuthorizationヘッダーに入れるのが一般的です。公式リファレンスのとおり、SendWebRequest()の後には呼べません。

using (UnityWebRequest request = UnityWebRequest.Get("https://example.com/api/me"))
{
    request.SetRequestHeader("Authorization", "Bearer " + token);
    request.SetRequestHeader("Accept", "application/json");
    yield return request.SendWebRequest();

    Debug.Log(request.GetResponseHeader("Content-Type"));
}

自由に設定できないヘッダーもあります。

  • Accept-Encodingは対応する圧縮形式が自動で入り、別の値は無視されるか失敗の原因になります。Content-Lengthも自動で設定されます。
  • Host・Origin・Referer・Connectionなどは、プラットフォームによって上書き・無視されるため、設定しないよう公式が勧めています。
  • Web(WebGL)ビルドでは、Cookie・Cookie2・User-Agentはブラウザーが設定するため、独自の値を付けられない場合があります。

レスポンスヘッダーはGetResponseHeader("Content-Type")で1つずつ、GetResponseHeaders()でDictionary<string, string>としてまとめて取れます。ただしWebビルドで別ドメインのAPIを呼ぶ場合、読めるのはブラウザーが公開するヘッダーだけです。Content-Typeなどの基本的なもの以外は、サーバーがAccess-Control-Expose-Headersで公開を許可している必要があります(Fetch Standard)。

timeoutの仕様:単位は秒・既定0は無制限

timeoutプロパティは、応答が無いまま指定秒数が過ぎたら通信を打ち切る設定です。既定値は0で、0は「タイムアウトを適用せず応答まで待つ」を意味します。モバイル回線では応答が返らないまま待ち続けることがあるため、ゲームの通信には必ず値を入れてください。時間切れのときはrequest.errorにRequest timeoutが入ります。

ソース(UnityWebRequest.bindings.cs)を読むと、実装上の注意点が3つあります。

  • 整数の秒しか指定できない:型はintで、内部では値×1000ミリ秒に変換されます。0.5秒のような指定はできません。
  • 送信後は変更できない:SendWebRequest()の後に代入するとInvalidOperationException(cannot modify the timeout)が出ます。
  • 負の値は0になる:Math.Max(value, 0)で丸められ、タイムアウト無しと同じ扱いになります。

何秒にするかは処理で変えます。ランキングやログイン情報のような小さいJSONは10秒前後、数MBのダウンロードはファイルの大きさと想定する回線速度から長めに取ります。timeoutは通信全体を1つの値で区切るだけで、接続と受信を別々に制限する設定はありません。大きなファイルで「止まったまま」を見張りたいときは、request.downloadProgressやdownloadedBytesの増え方をコルーチン側で監視し、一定時間増えなければAbort()します。

エラー判定とリトライ:resultの5値とresponseCode

resultの5値による成功・失敗の分岐

resultプロパティはUnity 2020.1で追加され、それ以前のisNetworkError・isHttpErrorはUnity 2020.2でObsoleteになりました。古い記事のコードは、次の表のとおり置き換えます。

result 状態 例 旧プロパティ
InProgress 送信中 完了前 –
Success 成功 200番台 –
ConnectionError サーバーと通信できない 接続不可・TLS失敗・時間切れ isNetworkError
ProtocolError サーバーがエラーを返した 404・500 isHttpError
DataProcessingError 受信データを処理できない 壊れた画像の変換失敗 –

定義はUnityWebRequest.Resultのリファレンスにあります。ProtocolErrorのときもサーバーが返した本文はdownloadHandler.textで読めるので、APIのエラーメッセージ(JSON)をログに残せます。

responseCodeが-1や0になるとき

responseCodeはサーバーが返したHTTPステータス(200・404・500など)で、リダイレクトを挟んだ場合は最後の応答の値です。公式リファレンスは、まだ応答を処理していないときの値を-1と説明しています。送信が完了した後も-1や0のままなら、有効なHTTPステータスを取得できていない(接続できない・時間切れ・HTTP接続の禁止など)と考えて、resultとerrorの文言で原因を見ます。成否をresponseCode == 200で判定するのも避けます。201や204のような成功を失敗と誤認し、受信データの変換に失敗したDataProcessingErrorも見分けられないためです。

リトライ対象の判断:接続失敗・408・429・一時的な5xx

UnityWebRequestには自動の再試行がありません。再試行の候補にするのは、時間をおけば回復しうる失敗です。ConnectionErrorのうち回線断や時間切れ、408(タイムアウト)・429(リクエスト過多)・500・502・503・504がこれに当たります。同じConnectionErrorでもTLSの確立失敗やHTTP接続の禁止は設定の問題なので、待っても直りません。400・401や、501(未実装)・505(HTTPバージョン非対応)も送り直しでは結果が変わりません。最終的には、呼び出すAPIの仕様と、同じ要求を2回処理しても問題ないか(冪等性)で決めます。待ち時間は倍々に増やし、多数の端末が同じ瞬間に再送しないよう揺らぎを足します。429や503でRetry-Afterヘッダーが返ったときは、その秒数より前に送り直さないのが原則です(RFC 9110)。次のコードはその解析を省いています。

IEnumerator GetWithRetry(string url, int maxAttempts = 3)
{
    for (int attempt = 1; attempt <= maxAttempts; attempt++)
    {
        using (UnityWebRequest request = UnityWebRequest.Get(url))
        {
            request.timeout = 10;
            yield return request.SendWebRequest();

            if (request.result == UnityWebRequest.Result.Success)
            {
                Debug.Log(request.downloadHandler.text);
                yield break;
            }

            // 一時的な失敗だけを再試行する。400・401・501などは送り直しても結果が変わらない
            long code = request.responseCode;
            bool retryable = request.result == UnityWebRequest.Result.ConnectionError
                || code == 408 || code == 429
                || code == 500 || code == 502 || code == 503 || code == 504;
            if (!retryable || attempt == maxAttempts)
            {
                Debug.LogError($"失敗: {request.responseCode} {request.error}");
                yield break;
            }
        }
        // 既定の3回なら待機は1秒・2秒の2回。倍々の待ち時間に揺らぎを足す
        float wait = Mathf.Pow(2, attempt - 1) + UnityEngine.Random.Range(0f, 0.5f);
        yield return new WaitForSecondsRealtime(wait); // timeScale=0でも止まらない
    }
}

1回ごとに新しいUnityWebRequestを作り直している点に注意してください。送信済みのインスタンスは再送できません。待機にWaitForSecondsRealtimeを使うのは、Time.timeScaleを0にしてゲームを一時停止しても再試行の待ちが止まらないようにするためです。指数バックオフと再試行回数の上限の決め方はリトライパターンとは?指数バックオフ・ジッター・リトライ予算の実装判断を解説で詳しく扱っています。POSTで再送するときは、サーバー側で同じリクエストを二重に処理しない仕組み(リクエストIDなど)が必要です。

async/awaitでの記述:Unity 2023.1以降のAwaitable

Unity 2023.1でAsyncOperationにGetAwaiter()拡張メソッドが追加されました(UnityCsReferenceのAwaitable.AsyncOperation.cs)。SendWebRequest()の戻り値UnityWebRequestAsyncOperationはAsyncOperationを継承しているので、Unity 6ではUniTaskなどの外部ライブラリ無しでawaitできます。

using System;
using System.Threading;
using UnityEngine;
using UnityEngine.Networking;

public class AwaitSample : MonoBehaviour
{
    async void Start()
    {
        try
        {
            string text = await GetTextAsync("https://example.com/api/score", destroyCancellationToken);
            Debug.Log(text);
        }
        catch (OperationCanceledException)
        {
            Debug.Log("オブジェクト破棄で中断");
        }
        catch (Exception e)
        {
            Debug.LogError(e.Message);
        }
    }

    static async Awaitable<string> GetTextAsync(string url, CancellationToken token)
    {
        using UnityWebRequest request = UnityWebRequest.Get(url);
        request.timeout = 10;
        // トークンが取り消されたら通信そのものを止める
        using (token.Register(() => request.Abort()))
        {
            await request.SendWebRequest();
        }
        token.ThrowIfCancellationRequested();

        if (request.result != UnityWebRequest.Result.Success)
            throw new Exception($"{request.result} {request.responseCode} {request.error}");
        return request.downloadHandler.text;
    }
}

このコードでは、オブジェクトが破棄されたときに取り消されるdestroyCancellationTokenを渡し、取り消されたらrequest.Abort()で通信そのものを止めています。Awaitable.FromAsyncOperation(op, token)にトークンを渡す書き方もありますが、こちらは待つのをやめるだけで、通信が止まるかどうかはソースから読み取れません。通信を確実に止めたいときはAbort()を呼んでください。

結果を呼び出し元に返したい・try/catchで失敗をまとめて扱いたいならawait、既存コードがコルーチンで統一されているならコルーチンのままで構いません。async voidは例外が呼び出し元に伝わらないので、Startのような入口だけに使い、中では必ずtry/catchで受けます。

画像・音声・AssetBundleの取得API

画像はUnityWebRequestTexture.GetTextureで取得します。公式リファレンスによると、テクスチャへの変換はワーカースレッドで行われるため、Texture2D.LoadImageで自前変換するよりメインスレッドの負荷を抑えられます。

using (UnityWebRequest request = UnityWebRequestTexture.GetTexture("https://example.com/icon.png"))
{
    yield return request.SendWebRequest();
    if (request.result != UnityWebRequest.Result.Success)
    {
        Debug.LogError(request.error);
        yield break;
    }
    Texture2D tex = DownloadHandlerTexture.GetContent(request);
    GetComponent<Renderer>().material.mainTexture = tex;
}

音声はUnityWebRequestMultimedia.GetAudioClip(url, AudioType.MPEG)のように形式を指定し、DownloadHandlerAudioClip.GetContent(request)でAudioClipを取り出します。AssetBundleはUnityWebRequestAssetBundle.GetAssetBundle(url)とDownloadHandlerAssetBundle.GetContent(request)の組み合わせです。古い記事にあるUnityWebRequest.GetTexture・UnityWebRequest.GetAssetBundleはエラー扱いのObsoleteで、Unity 6ではコンパイルが通りません。

HTTP接続・WebGL・Disposeで失敗する原因と対処

「Insecure connection not allowed」の対処:HTTPS化と開発時のHTTP許可

Unity 2022.1から、UnityWebRequestは既定でHTTPSだけを許可します。http://のURLに送るとInvalidOperationException: Insecure connection not allowedが出ます。設定はEdit > Project Settings > Player > Other SettingsのAllow downloads over HTTPで、選択肢は3つです(InsecureHttpOption)。

設定値 HTTP接続 使いどころ
Not Allowed(既定) 禁止 本番ビルド
Allowed in Development Builds 開発ビルドだけ許可 HTTPの検証サーバーを使う間
Always Allowed 常に許可 HTTPSにできない接続先が残る場合

この設定はすべてのプラットフォームに効き、ビルド時の値が使われます。実行中には変えられません。localhostと127.0.0.1への接続は設定に関係なく許可されるので、手元の開発サーバーはNot Allowedのままでも呼べます。Always Allowedは通信内容が平文で流れるため、本番では接続先をHTTPSにするのが先です。

WebGL(Web)通信におけるCORSとFetch APIの制約

Web networkingのマニュアルによると、WebビルドのUnityWebRequestはブラウザーのFetch APIで実装されています。そのため、ゲームを置いたドメインと別のサーバーへ送るには、相手サーバーがCORSで許可している必要があります。エディタでは動くのにWebGLビルドだけ失敗し、ブラウザーのコンソールに「Cross-Origin Request Blocked」が出ていれば、原因はUnity側ではなくサーバーのAccess-Control-Allow-Originなどの応答ヘッダーです。設定方法はCORSとは?仕組み・プリフライト・サーバー設定例・エラー解決を実装目線で解説を参照してください。

Webでは他にも次の制約があります。

  • while (!request.isDone) {}のように完了を同期で待つコードは使えない(ブラウザーが処理を止める)。コルーチンかawaitで待つ。
  • System.Net.Http(HttpClient)やSystem.Net.Socketsは使えない。Webで通信するならUnityWebRequestを直接使う。
  • CertificateHandlerによる証明書の独自検証は対象外(Android・iOS・デスクトップなどに限られる)。

WebGLビルドの手順や対応ブラウザーはWebGLとは?仕組み・対応ブラウザの確認・三角形を描くコードとUnityビルドまで解説にまとめています。

Disposeによるネイティブ資源とハンドラーの解放

UnityWebRequestはネイティブ(C++側)の資源を持っています。公式リファレンスは、成功・失敗にかかわらず使い終わったらDisposeを呼ぶこと、例外が出ても確実に片付くようusing文を使うことを勧めています。disposeDownloadHandlerOnDispose・disposeUploadHandlerOnDispose・disposeCertificateHandlerOnDisposeの既定値はいずれもtrueで、本体を破棄すればハンドラーも一緒に破棄されます。ハンドラーを使い回すためにこれらをfalseにしたときは、ハンドラーのDisposeを自分で呼びます。

旧WWWクラスからUnityWebRequestへの移行対応表

WWWクラスはUnity 6(6000.6.0f1のソース)でも残っていますが、「Use UnityWebRequest, a fully featured replacement which is more efficient and has additional features」というObsolete属性が付いています。ソースを読むと、現在のWWWは内部でUnityWebRequestを作って送信するだけのラッパーです。新しく書くコードでは使わず、残っている箇所は次の対応表で置き換えます。

WWW UnityWebRequest
new WWW(url) UnityWebRequest.Get(url)
new WWW(url, form) UnityWebRequest.Post(url, form)
yield return www yield return request.SendWebRequest()
www.error request.resultとrequest.error
www.text / www.bytes request.downloadHandler.text / .data
www.texture(生成) UnityWebRequestTexture.GetTexture(url)
www.texture(取り出し) DownloadHandlerTexture.GetContent(request)
WWW.EscapeURL(s) UnityWebRequest.EscapeURL(s)
// 旧:WWW(Obsolete)
WWW www = new WWW(url);
yield return www;
if (string.IsNullOrEmpty(www.error)) Debug.Log(www.text);

// 新:UnityWebRequest
using (UnityWebRequest request = UnityWebRequest.Get(url))
{
    yield return request.SendWebRequest();
    if (request.result == UnityWebRequest.Result.Success) Debug.Log(request.downloadHandler.text);
}

移行で抜けやすいのは2点です。WWWを使った古いコードはDisposeを書いていないことが多く、置き換えた後もusingを付け忘れること。そして、WWWのコンストラクターは生成した時点で通信を始めますが、UnityWebRequestはSendWebRequest()を呼ぶまで何も送らないことです。timeoutやヘッダーは、その間に設定します。

HttpClientとの使い分け:Unity 6.5のUnityHttpMessageHandler

Unity 6.5(6000.5)でUnityHttpMessageHandlerが追加されました。UnityCsReferenceでは6000.4.0f1に無く、6000.5.0f1から存在します。.NET標準のHttpClientに渡すと、HttpClientの送受信をUnityWebRequestが担うようになります。

using System.Net.Http;
using UnityEngine;
using UnityEngine.Networking;

public class HttpClientSample : MonoBehaviour
{
    async void Start()
    {
        try
        {
            Debug.Log(await GetAsync("https://example.com/api/score"));
        }
        catch (HttpRequestException e)
        {
            Debug.LogError(e.Message);
        }
    }

    static async Awaitable<string> GetAsync(string url)
    {
        // Unity 6.5(6000.5)以降。HttpClientの下回りをUnityWebRequestにする
        using var client = new HttpClient(new UnityHttpMessageHandler());
        return await client.GetStringAsync(url);
    }
}

このクラスが役に立つのは、HttpClientを前提にしたライブラリをUnityで使う場面です。公式の説明では、gRPCのGrpcChannelのHttpHandlerに渡す使い方が例示されています。判断の基準は次のとおりです。

  • 自分でREST APIを呼ぶだけなら、UnityWebRequestを直接使う。Web(WebGL)でも同じコードで動き、この記事のサンプルがそのまま使える。
  • HttpClient前提のSDKやgRPCクライアントを入れたいなら、Unity 6.5以降でUnityHttpMessageHandlerを渡す。Unity 6.3 LTSを使い続けるプロジェクトでは使えない。
  • HttpClientをハンドラー無しで使う書き方は、Webビルドで動かないので避ける。

通信まわりの実装をゲームごとに作り直さず、サーバー側のAPI設計から含めて固めたい場合は、ゲームアプリ開発の支援内容も参考にしてください。

よくある質問

UnityWebRequestにタイムアウトはありますか?

あります。request.timeout = 10;のように秒数(int)で指定します。既定値の0は時間制限なしです。SendWebRequest()の後には変更できないので、送信前に設定してください。

UnityWebRequest.PostでJSONを送るにはどうすればよいですか?

Unity 2022.2以降はUnityWebRequest.Post(url, json, "application/json")を使います。2022.1以前はnew UnityWebRequest(url, "POST")にUploadHandlerRawとDownloadHandlerBufferを付け、Content-Typeヘッダーを設定します。引数2つのPost(url, json)はURLエンコードされるため使いません。

WWWクラスはまだ使えますか?

Unity 6でもクラス自体は残っていますが、Obsoleteで警告が出ます。公式はUnityWebRequestを完全な置き換えとしているので、移行してください。WWW.EscapeURLもUnityWebRequest.EscapeURLに置き換えられます。

responseCodeが0や-1になるのはなぜですか?

HTTPの応答を受け取れていないためです。公式は応答を処理する前の値を-1と説明しています。接続できない・時間切れ・HTTP接続の禁止などが原因なので、resultがConnectionErrorかどうかとerrorの文言を確認します。

WebGLビルドだけ通信が失敗するのはなぜですか?

WebではUnityWebRequestがブラウザーのFetch APIで動くため、別ドメインのサーバーにはCORSの許可が必要です。ブラウザーのコンソールにCORSのエラーが出ていれば、サーバー側にAccess-Control-Allow-Originなどの応答ヘッダーを追加します。

関連記事

お気に入りに入れた記事の一覧

一創の公式 SNS

X では毎朝の新着記事と IT ニュースの速報を、YouTube・TikTok・Instagram・LinkedIn・Facebook では記事の解説動画を配信しています。

この記事は以下の記事からリンクされています

資料請求

今日のトレンド記事 直近 24 時間で、いつもより多く読まれている記事

  1. 2026.11.03 テックブログ クラブツーリズム不正アクセス:約432万件の対象確認と偽メールの見分け方・流出検知の設計
  2. 2026.11.04 テックブログ CVE-2026-119977:WordPress更新中のRCEと安全な更新手順
  3. 2026.10.29 テックブログ ソニー生命の情報漏洩38.5万件|ログインできない理由、再開状況と窓口の電話番号
  4. 2026.11.03 テックブログ ノジマ不正アクセスで約700万件漏えい:対象確認・窓口と乗っ取り注文を止める実装
  5. 2026.11.02 テックブログ アララの不正アクセス:メール約7,700万件の持ち出しと契約企業が行うAPIキー再設定・代替送信・連名報告

RELATED POSTS 関連記事

目次