LoginSignup
3
5

【Unity】UnityWebRequestの詳細なエラー内容で処理を分岐する方法

Last updated at Posted at 2024-02-23

はじめに

UnityでHTTP(S)通信したいなーと思ったら通常は組み込みの UnityWebRequest を使うと思うのですが、詳細なエラー内容で分岐できなくて困ったので調べました。

大まかなエラーで分岐する

コガネブログさんの記事内のコードを以下に引用します。

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

public class Example : MonoBehaviour
{
    private IEnumerator Start()
    {
        var request = UnityWebRequest.Get( "https://baba-s.hatenablog.com/" );

        yield return request.SendWebRequest();

        switch ( request.result )
        {
            case UnityWebRequest.Result.InProgress:
                Debug.Log( "リクエスト中" );
                break;

            case UnityWebRequest.Result.Success:
                Debug.Log( "リクエスト成功" );
                break;

            case UnityWebRequest.Result.ConnectionError:
                Debug.Log
                (
                    @"サーバとの通信に失敗。
リクエストが接続できなかった、
セキュリティで保護されたチャネルを確立できなかったなど。"
                );
                break;

            case UnityWebRequest.Result.ProtocolError:
                Debug.Log
                (
                    @"サーバがエラー応答を返した。
サーバとの通信には成功したが、
接続プロトコルで定義されているエラーを受け取った。"
                );
                break;

            case UnityWebRequest.Result.DataProcessingError:
                Debug.Log
                (
                    @"データの処理中にエラーが発生。
リクエストはサーバとの通信に成功したが、
受信したデータの処理中にエラーが発生。
データが破損しているか、正しい形式ではないなど。"
                );
                break;

         default: throw new ArgumentOutOfRangeException();
        }
    }
}

UnityWebRequest.Result という enum で分岐できるっぽいのですが、これは以下の5種類しかありません。

説明
InProgress The request hasn't finished yet.
Success The request succeeded.
ConnectionError Failed to communicate with the server. For example, the request couldn't connect or it could not establish a secure channel.
ProtocolError The server returned an error response. The request succeeded in communicating with the server, but received an error as defined by the connection protocol.
DataProcessingError Error processing data. The request succeeded in communicating with the server, but encountered an error when processing the received data. For example, the data was corrupted or not in the correct format.

https://docs.unity3d.com/2020.2/Documentation/ScriptReference/Networking.UnityWebRequest.Result.html)

成功 or 失敗 くらいの粒度で知りたい場合は別にいいのですが、例えば

  • 通信に失敗したときにエラーコードを表示してそれをもとに問い合わせてもらう
  • タイムアウトしたら再度リクエストを送信する

みたいな場合には情報が無に等しく、途方に暮れてしまいます。

詳細なエラーで分岐する

より詳細なエラーを知りたい場合は UnityWebRequest.error が使えます。

switch (unityWebRequest.error)
{
    case "Cannot resolve destination host":
        DoSomething();
        break;

    ...

    default: throw new ArgumentOutOfRangeException();
}

この方法には大きな問題点があって、 error の文字列が公開・一覧化されていないということです。

上のコードで言うところの "Cannot resolve destination host" みたいな文字列が取りうる値がわからなければ分岐しようがありません。

こんなことってある???

エラーの文字列を知る

とりあえずソースコードを読めばなんとかなるでしょ、ということでUnityCsReferenceを確認してみます。

UnityWebRequest.bindings.cs

internal enum UnityWebRequestError
private extern static string GetWebErrorString(UnityWebRequestError err);

エラーの文字列が決め打ちしてあるわけではないですが、怪しいやつが2つ見つかりました。

リフレクションを使って GetWebErrorString(UnityWebRequestError err) を呼んでみます。

GetAllErrorStrings.cs
using System;
using System.Linq;
using System.Reflection;
using UnityEngine;
using UnityEngine.Networking;

public static class GetAllErrorStrings
{
    [RuntimeInitializeOnLoadMethod]
    static void RuntimeInitializeOnLoadMethod()
    {
        var errorCodes = Enum.GetValues(typeof(UnityWebRequest.UnityWebRequestError))
            .Cast<UnityWebRequest.UnityWebRequestError>()
            .ToList();

        var method = typeof(UnityWebRequest).GetMethod("GetWebErrorString", BindingFlags.Static | BindingFlags.NonPublic);
        var str = "";

        foreach (var errorCode in errorCodes)
        {
            var error = method.Invoke(null, new object[] { errorCode });
            str += $"{errorCode}:{error}\n";
        }
        
        Debug.Log(str);
    }
}

internalUnityWebRequestError にアクセスしていてそのままではコンパイルエラーになります。こちらを参考に UnityEngine.UI などを参照する *.asmref を追加してください。

このスクリプトを以下の環境で実行した結果は次の表の通りになりました。

  • 実行環境
    • OS:macOS Sonoma 14.3
    • Unity:2022.3.18f1
    • Unityエディタ上で実行
errorCode error
OK
OKCached
Unknown Unknown Error
SDKError Backend Initialization Error
UnsupportedProtocol Unsupported Protocol
MalformattedUrl Malformed URL
CannotResolveProxy Cannot resolve proxy
CannotResolveHost Cannot resolve destination host
CannotConnectToHost Cannot connect to destination host
AccessDenied Access denied
GenericHttpError Generic/unknown HTTP error
WriteError Unable to write data
ReadError Unable to read data
OutOfMemory Out of memory
Timeout Request timeout
HTTPPostError Error during HTTP POST transmission
SSLCannotConnect Unable to complete SSL connection
Aborted Request aborted
TooManyRedirects Redirect limit exceeded
ReceivedNoData Received no data in response
SSLNotSupported Destination host does not support SSL
FailedToSendData Failed to transmit data
FailedToReceiveData Failed to receive data
SSLCertificateError Destination host has an erroneous SSL certificate
SSLCipherNotAvailable Unable to load SSL Cipher for verification
SSLCACertError SSL CA certificate error
UnrecognizedContentEncoding Unrecognized content-encoding
LoginFailed Login failed
SSLShutdownFailed SSL shutdown failed
RedirectLimitInvalid Redirect limit is invalid
InvalidRedirect Encountered invalid redirect (missing Location header?)
CannotModifyRequest Cannot modify request at this time
HeaderNameContainsInvalidCharacters Header name contains invalid characters
HeaderValueContainsInvalidCharacters Header value contains invalid characters
CannotOverrideSystemHeaders Cannot override system-specified headers
AlreadySent Request already transmitted
InvalidMethod Invalid HTTP Method
NotImplemented Not implemented
NoInternetConnection No Internet Connection
DataProcessingError Data Processing Error, see Download Handler error
InsecureConnectionNotAllowed Insecure connection not allowed

基本的には表の右側のテキストを使って分岐すればいいはずですが、iOSやAndroidの実機では異なる値になるかもしれないので、実機でも確認したほうが良さそうです(確認できたら追記します)。

また、これらのエラー文字列はUnityのバージョンによっても異なる場合があるので、自分が使っているバージョンのUnityで実際に出力してみることをおすすめします。

感想

こういうムダな努力をしたくなければ素直に Best HTTP を買うのが良さそう。

いただいたコメント

3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5