コードで Remote Settings にアクセスするには、Unity スクリプティング API の RemoteSettings クラスを使用します。RemoteSettings
クラスには、RemoteSettings.GetString()
など Remote Settings にアクセスするための関数だけでなく、設定が取得されたり更新されたときに関数を呼び出すのに使うイベントが備わっています。
イベント | 目的 |
---|---|
BeforeFetchFromServer |
RemoteSettings クラスが Remote Settings を取得するためのネットワーク要求を行う直前に送信されます。 |
Completed | ネットワーク要求が完了したときに送信されます。Completed は、たとえネットワーク要求が失敗して Remote Settings に変更がない場合でも、常に送信されます。デリゲート関数に渡された serverResponse コードを使用して、要求が成功したか失敗したかを判断できます。このパラメーターには、成功を示す 200 など、標準の HTTP 応答コードの 1 つが含まれています。 |
Updated | ネットワーク要求が正常に完了した後に送信されます。ただし、前回のチェック以降に Remote Settings が変更された場合のみに限られます。 ノート: Unity 2018.1 より前では、設定の変更がない場合でも Updated イベントは常に送信されていました。ゲームに設定を適用するためにデリゲート関数に依存している場合は、変更の有無にかかわらず、Updated イベントではなく Completed イベントを使用する必要があります。 |
これらのイベントのハンドラー関数は、アプリケーションの起動時、例えば Unity シーンに最初にロードされる MonoBehaviour の Awake()
関数の中などで、できるだけ早く登録する必要があります。
なぜなら、設定を取得するには ネットワークトランザクション が必要なので、RemoteSettings
オブジェクトはそのイベントを非同期的に送信します。様々なプラットフォーム上で、あるいは同じプラットフォームの毎回の起動時に、ハンドラー関数が他のイベントと比べて同じ順序で呼び出されるとは限りません。常に適切なデフォルト値を使用して構成変数を初期化し、アプリケーションの起動時にイベントハンドラーが異なるタイミングで呼び出される可能性に対処します。
コードサンプル
以下の例は、Remote Settings を使用してゲームの問題を調整するための多くのプロパティーを定義し、それらのプロパティーを更新するクラスを示しています。
using UnityEngine;
public class RemoteTuningVariables : MonoBehaviour {
public float DefaultSpawnRateFactor = 1.0f;
public float DefaultEnemySpeedFactor = 1.0f;
public float DefaultEnemyStrengthFactor = 1.0f;
public static float SpawnRateFactor{ get; private set; }
public static float EnemySpeedFactor{ get; private set; }
public static float EnemyStrengthFactor{ get; private set; }
void Start () {
SpawnRateFactor = DefaultSpawnRateFactor;
EnemySpeedFactor = DefaultEnemySpeedFactor;
EnemyStrengthFactor = DefaultEnemyStrengthFactor;
RemoteSettings.Completed += HandleRemoteSettings;
}
private void HandleRemoteSettings(bool wasUpdatedFromServer, bool settingsChanged, int serverResponse){
SpawnRateFactor
= RemoteSettings.GetFloat ("SpawnRateFactor", DefaultSpawnRateFactor);
EnemySpeedFactor
= RemoteSettings.GetFloat ("EnemySpeedFactor", DefaultEnemySpeedFactor);
EnemyStrengthFactor
= RemoteSettings.GetFloat ("EnemyStrengthFactor", DefaultEnemyStrengthFactor);
}
}
このクラスは、RemoteSettings.GetFloat()
メソッドを呼び出してデフォルト値を設定します。RemoteSettings
オブジェクトが指定されたキーを見つけられない場合 (例えば、キー名のスペルが間違っている場合など)、このメソッドはデフォルト値を変数に割り当てます。そうでない場合は、GetFloat()
と GetInt()
メソッドは数値に 0 を割り当て、GetString()
は文字列に空の文字列を割り当て、GetBool()
は bool 変数に false を割り当てます。
Remote Settings が取得される前に別のクラスが設定にアクセスし、以前キャッシュされた設定がローカルで利用できない場合、クラスは Start()
メソッドのプロパティーにも同じデフォルト値を割り当てます。Start()
メソッドでデフォルト値を割り当てることで、プロパティーに常に適当な値が設定されます。
ゲーム内にクラスがいくつかあり、異なるタイミングで Remote Settings にアクセスする場合、非同期ネットワーク要求が完了する前に設定にアクセスするオブジェクトもあれば、ネットワーク要求の完了後に設定にアクセスするオブジェクトもあります。 そのため、一貫性のない設定値になる可能性があります。この非一貫性の問題を回避するには、設定にアクセスする前に非同期ネットワーク要求が完了するのを待つか、現在のセッションの開始時に既存の設定をそのまま使用するかです。 後者の場合、ローカル設定はバックグラウンドで更新され、プレイヤーには次のセッションで更新された設定が表示されます。
方法 | 利点 | 欠点 |
---|---|---|
要求の完了を待機 | - 設定値に一貫性があります - 常に最新の設定を使用できます |
- 設定の状況によって不確定な遅延が発生します - 非同期のコードの複雑性 |
既存の設定を使用 | - 設定値に一貫性があります - 設定は即座に使用可能です |
- 最新の設定値は次のセッションまで使用できません - 初めてゲームを行う時に、使用可能な設定がありません (デフォルト値を使用します) |
次の例は、Analytics サービスから取得した Remote Settings の最新バージョンに基づいてプロパティーを割り当てるプロバイダークラスを示しています。RemoteSettings
クラスはバックグラウンドで設定を更新するため、設定の変更はすべて (現在のセッションではなく) 次のセッションで使用されます。次の例ではシングルトンパターンを使用しているため、RemoteSettings
クラスがいつリモート更新を受信するかにかかわらず、これらの設定を使用するゲームのすべての部分で同じ値を取得します。
using UnityEngine;
public class RemoteSettingProvider : MonoBehaviour {
public float DefaultSpawnRateFactor = 1.0f;
public float DefaultEnemySpeedFactor = 1.0f;
public float DefaultEnemyStrengthFactor = 1.0f;
public float SpawnRateFactor{ get; private set; }
public float EnemySpeedFactor{ get; private set; }
public float EnemyStrengthFactor{ get; private set; }
// シングルトンパターン
private static RemoteSettingProvider _instance;
public static RemoteSettingProvider Instance
{
get { return _instance; }
}
void Awake()
{
if (_instance != null && _instance != this)
{
Destroy(this.gameObject);
return;
}
_instance = this;
DontDestroyOnLoad(this.gameObject);
//リモート更新前は既存の設定を使用します。または、
//既存の設定がまだない場合は、デフォルト値を使用します。
SpawnRateFactor
= RemoteSettings.GetFloat("SpawnRateFactor", DefaultSpawnRateFactor);
EnemySpeedFactor
= RemoteSettings.GetFloat("EnemySpeedFactor", DefaultEnemySpeedFactor);
EnemyStrengthFactor
= RemoteSettings.GetFloat("EnemyStrengthFactor", DefaultEnemyStrengthFactor);
}
}
この方法を使用すると、インストール後にプレイヤーが初めてゲームを実行したときには、常にデフォルトの設定が使用されます。
RemoteSettings.GetCount()
を使用してローカル設定が存在するかどうかを確認するハイブリッドの方法を使用することもできます。設定がローカルに存在する場合はすぐにその設定を使用できますが、存在しない場合はイベントハンドラーを加え、設定の Updated
イベントを待ちます。
SpawnRateFactor
= RemoteSettings.GetFloat("SpawnRateFactor", DefaultSpawnRateFactor);
EnemySpeedFactor
= RemoteSettings.GetFloat("EnemySpeedFactor", DefaultEnemySpeedFactor);
EnemyStrengthFactor
= RemoteSettings.GetFloat("EnemyStrengthFactor", DefaultEnemyStrengthFactor);
if(RemoteSettings.GetCount() == 0){
//設定がない場合は、リモートで取得します
RemoteSettings.Updated += HandleRemoteSettings;
Ready = false;
} else {
Ready = true;
}
Remote Settings を使う他のクラスはプロバイダークラスの Ready
プロパティーをチェックしてその設定にアクセスしても良いかどうか判断しなければなりません。次の例は、設定を待機し、さらに設定可能なタイムアウトを使用するクラスを示しています。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RemoteSettingConsumer : MonoBehaviour {
public float SpeedFactor = 0;
public float StrengthFactor = 0;
public float SpawnRateFactor = 0;
public float Timeout = 0.125f;
void Start () {
StartCoroutine(GetRemoteSettings(Time.time));
}
IEnumerator GetRemoteSettings(float startTime){
while(!RemoteSettingProvider.Instance.Ready && (Time.time - startTime) < Timeout)
yield return null;
SpeedFactor = RemoteSettingProvider.Instance.EnemySpeedFactor;
StrengthFactor = RemoteSettingProvider.Instance.EnemyStrengthFactor;
SpawnRateFactor = RemoteSettingProvider.Instance.SpawnRateFactor;
}
}
Remote Settings が使用可能になる前にタイムアウトになったた場合は、デフォルト値が使用されます。タイムアウトを使用すると、ネットワークトランザクションが非常に短時間で完了する正常な場合に、ゲームが最新の設定を取得できます。ネットワーク障害の場合にリクエスト自体がタイムアウトするのを待つことによって、過度に起動を遅らせることがありません。