はじめに
ネットワークに繋がって いる/いない のチェックは下記コードを使っていましたが、こちらは正確ではありませんでした。
if( Application.internetReachability != NetworkReachability.NotReachable )
公式に注意書きがありました。これは「機内モード」など、あくまで端末側の設定をチェックするもので、実際の接続をチェックするものではないとのこと。
注:このプロパティは、実際の接続性を判断するために使用しないでください。例:デバイスはホットスポットに接続されていても、ネットワークへの実際の経路を持っていないことがあります。
https://docs.unity3d.com/ScriptReference/Application-internetReachability.html
今回コードを見直したのでご紹介します。
サンプルコード
実際にネットワークに繋がっているかチェックするサンプルです。繋がっていればtrue、繋がっていなければfalseを返します。UniTaskを使います。
- Unity 2021.3.11
- UniTask 2.3.1
using UnityEngine;
using UnityEngine.Networking;
using Cysharp.Threading.Tasks;
using System;
//インターネット接続確認
public static class OnlineChecker {
//テストアクセスするURL
private static readonly string CHECK_TARGET_URL = "https://httpbin.org";
public async static UniTask<bool> IsOnline(int timeOut = 3000)
{
if(Application.internetReachability == NetworkReachability.NotReachable) return false;
bool bo = false;
var request = new UnityWebRequest(CHECK_TARGET_URL);
var task1 = request.SendWebRequest().ToUniTask();
var task2 = UniTask.Delay(timeOut);
try
{
DevLog.Log($"アクセス-開始 {CHECK_TARGET_URL}");
var result = await UniTask.WhenAny(task1,task2);
if(result.result.result == UnityWebRequest.Result.Success)
{
DevLog.Log($"アクセス-成功 {CHECK_TARGET_URL}");
bo = true;
}
}
catch(Exception e)
{
DevLog.LogWarning($"例外-失敗 {e}");
}
finally
{
await UniTask.WaitUntil(() => request.isDone);
request.Dispose();
DevLog.Log($"アクセス-廃棄");
}
return bo;
}
}
コード解説
OnlineChecker クラスはシーンに配置する必要はありません。
public static class OnlineChecker
テストアクセスしている「httpbin」は通信テストに便利なWebサービスです。本番では所持しているサーバーなどに置き換えてください。
private static readonly string CHECK_TARGET_URL = “https://httpbin.org”;
![](https://softantenna.com/blog/wp-content/uploads/2018/03/Is_20180302_210355-1.jpg)
IsOnline() メソッドはタイムアウト用の int 値(デフォルト3秒)を引数にしていて、Unitak で Bool型を返しています。キャンセルは想定していていませんが、外部からキャンセルできるようにCancellationTokenを渡してもいいかもしれません。
public async static UniTask<bool> IsOnline( int timeOut = 3000 )
また、そもそも端末側でアクセス制限している場合はfalseを返します。
if(Application.internetReachability == NetworkReachability.NotReachable) return false;
Unityの過去バージョンではiOS14.2などでUnityWebRequest の timeoutが効かないことがあったようです。現在は修正されたようですが、、、
![](https://unity.com/themes/contrib/unity_base/images/og.jpg)
![](https://unity3d.com//media/images/elements/facebook_og_logo.png)
、、、私の環境ではtimeoutは機能しましたが、エラーを返してフリーズしてしまったので、UnityWebRequestをUnitask化して、UniTask.WhenAny()でUniTask.Delay()と掛け合わせて、時間を制限するようにしました。
var request = new UnityWebRequest(CHECK_TARGET_URL);
var task1 = request.SendWebRequest().ToUniTask();
var task2 = UniTask.Delay(timeOut);
var result = await UniTask.WhenAny(task1,task2);
UnityWebRequest をインスタンスしてtry-catch-finallyを使って、アクセス-成功/失敗/廃棄を処理しています。アクセスに失敗したら false 、成功したら true を返します。
try
{
DevLog.Log($”アクセス-開始 {CHECK_TARGET_URL}”);
var result = await UniTask.WhenAny(task1,task2);
if(result.result.result == UnityWebRequest.Result.Success)
{
DevLog.Log($”アクセス-成功 {CHECK_TARGET_URL}”);
bo = true;
}
}
catch(Exception e)
{
DevLog.LogWarning($”アクセス-失敗 {e}”);
}
finally
{
await UniTask.WaitUntil(() => request.isDone);
request.Dispose();
DevLog.Log($”アクセス-廃棄”);
}
return bo;
つまずいたのは、request.Dispose()するタイミングです。UniTask.WhenAnyが終了してから若干遅延があるようで、request.isDoneを待ってからDisposeするようにしました。
await UniTask.WaitUntil(() => request.isDone);
request.Dispose();
使い方
任意の場所からOnlineChecker.IsOnline()を呼び出して、bool値を受け取り、分岐させて処理を実行します。タイムアウトの時間を3秒から変更したい場合は数値を指定してください。
void Start()
{
_OnlineChecker().Forget();
}
//ネットワークチェック
async UniTaskVoid _OnlineChecker()
{
var bo = await OnlineChecker.IsOnline(2000);
if(bo)
{
Debug.Log("成功した処理");
}
else
{
Debug.Log("失敗した処理");
}
}
![](https://kingmo.jp/kumonos/wp-content/uploads/2022/11/NLC5-300x282.jpg)
参考
![](https://teratail.com/img/ogpImages/imgFacebookShare.png)
![](https://cdn-ak.f.st-hatena.com/images/fotolife/k/kan_kikuchi/20210824/20210824145330.jpg)
![](https://blog-imgs-162.fc2.com/h/a/l/halcyonsystemblog/icons.png)