Update resources without App-Update
Autoyaでは、App本体のストアでのアップデートに頼らず、たとえリソースの使用中であってもリソースの更新を行うことができる。 また、複数のリストを同時に運用することが可能。
用語:リスト
AssetGraphで生成したAssetBundleList。 現在のAppで使用する可能性のある全てのAssetBundleの情報が記載されている。 フォーマットなどの詳細はAssetBundleを参照。生成は生成を参照。
クライアント側のリソース更新までの行程
Autoyaでは、リソース(AssetBundle)の管理の主導権はすべてサーバ側が握っており、任意のタイミングで特定のリソースを使わせることができる。
そのために、次のような前提を満たしている。
- クライアント側では、扱えるリスト名の一覧情報がRuntimeManifestで管理されている。
- CDNに、クライアント側のOS、与えるリストのバージョンに対応するAssetBundleがアップされている(参考:生成, デプロイ)。
- クライアント側からの任意のHTTPリクエストには、現在保持しているリスト名とそのバージョン値が記載されている。
- サーバはそれらが不服であれば、HTTPのレスポンスヘッダーにリソース更新用の特定値(resversion=value)を入れ、クライアントのリソースの更新を促すことができる。
- 特定値は常に入っていなくてもOKだし、入っていてもOK(必要な時だけつけるのを推奨)
レスポンスヘッダーに値が含まれている場合、次のようなフローが着火する。
いくつかのOverridePointsを通過し、このフローを最後まで通過すると、リストはサーバが指定したものへと更新された状態になる。
!注意!
リストの更新後、現在キャッシュされているABは、次回Load/Preload時にリストの内容を反映した最新のものになる。
あくまでもリストが更新されただけなので、現在メモリ上に展開されているABは影響を受けない。
なので、
- リストの更新
- これから使用するAssetに応じてPreloadで最新版のAssetBundleをロードしておく
- Asset使用時に最新版を動的にDL -> キャッシュしてキャッシュ後のABからAssetをロード
などのような行程を踏むことになる。
リソース更新用の特定値
特定値は、あらゆるAppからのリクエストに対してのレスポンスヘッダーに、resversion=value のような書き方で指定できる。 この resversion=value に、更新したいリストのidentityと、更新先のバージョン値を記述する。
キーは AuthSettings.cs/AUTH_RESPONSEHEADER_RESVERSION から変更可能。
public const string AUTH_RESPONSEHEADER_RESVERSION = "resversion";
valueのフォーマットはサーバ側で自由に設定でき、OverridePointsの関数 GetListIdentityAndNewVersionDescriptions で調整可能。
private KeyValuePair<string, string>[] GetListIdentityAndNewVersionDescriptions(string source)
{
var listInfosStrs = source.Split(',');
var identityAndNewVersionPairs = new KeyValuePair<string, string>[listInfosStrs.Length];
for (var i = 0; i < listInfosStrs.Length; i++)
{
var listInfosStr = listInfosStrs[i];
var identityAndVersion = listInfosStr.Split(':');
identityAndNewVersionPairs[i] = new KeyValuePair<string, string>(identityAndVersion[0], identityAndVersion[1]);
}
return identityAndNewVersionPairs;
}
サンプルでは、リスト名1:バージョン値1,リスト名2:バージョン値2,,, などのように、カンマ区切りで情報が来ることを想定している。
例えばサーバ側は resversion=リスト名1:バージョン値1,リスト名2:バージョン値2,,, などの値をレスポンスヘッダーにつければ、Appが保持しているリスト名1のリストのバージョンをバージョン値1に、リスト名2のバージョンをバージョン値2に変更できる。
この部分のフォーマットは上記の関数の内容を書き換えることで編集でき、最終的にどんなフォーマットであっても、KeyValuePair<string, string>型で{リスト名, バージョン値} のペアをリスト分だけ生成して返せればよい構造になっている。
現在オンメモリで使用しているABがある状態でのリスト更新について
Autoyaでは、リストの更新が発生した瞬間、App側で現在リソースを使用中であっても、安全にリソースの変更を行うことを補助する仕組みが入っている。
2段階のOverridePointsのメソッド呼び出しがあり、
OverridePoints/OnRequestNewAssetBundleList メソッドにて、リストのダウンロードURLの生成とダウンロード自体の可否を指定できる。
private Func<string, string, string, ShouldRequestOrNot> OnRequestNewAssetBundleList = (string basePath, string receivedNewAssetBundleIdentity, string rceivedNewAssetBundleListVersion) =>
{
var url = basePath + receivedNewAssetBundleIdentity + "/" + rceivedNewAssetBundleListVersion + "/" + receivedNewAssetBundleIdentity + ".json";
return ShouldRequestOrNot.Yes(url);
// return ShouldRequestOrNot.No();
};
ここで、basePath パラメータは、RuntimeManifestに含まれているurl値になる。現在のAutoyaでは、リストとABの取得URLはそのベースパスをRuntimeManifestに含まれている値から変更することはできない。
OverridePoints/ShouldUpdateToNewAssetBundleList メソッドにて、CurrentUsingBundleCondition パラメータに次のどれかの値が含まれた状態で実行される。
private Func<CurrentUsingBundleCondition, bool> ShouldUpdateToNewAssetBundleList = (CurrentUsingBundleCondition condition) =>
{
/*
according to your app's state & value of condition,
please select true(update assetBundleList) or false(cancel update assetBundleList now).
e,g,
when your app's state is under battle, and you determine that no need to change asset now,
should
retrun false.
list update will be postponed.
otherwise when your app's state is good state to update assets,
should
retrun true
for update assetBundleList.
app's assetBundleList will be updated to the latest and ready for load/download latest assetBundles.
using "Preload" feature on the beginning of app's state will help updating latest assets.
*/
return true;
};
サンプルでは一切の状況を判断せずtrueを返しているが、CurrentUsingBundleCondition パラメータには次のどれかが入り、状況に応じてリストを更新するかどうか判断するチャンスがある。
UsingAssetsAreChanged
// これから適応しようとしているリストに、現在使用している(オンメモリな)AssetBundleの最新版の情報が含まれている
NoUsingAssetsChanged,
// これから適応しようとしているリストには、現在使用している(オンメモリな)AssetBundleの更新は含まれていない
AlreadyUpdated
// すでに最新版のリストを取得してある(よって何もする必要がない)
クライアント開発者は、これらの情報と現在のAppの遷移状態を元に、リストの更新を許せるかどうかを判断し、挙動を制御することが可能になっている。
- リクエストのurlに対して細かい調整をしないといけないかも? リクエスト時のクエリとか そのへんはどこで編集するといいのかな。あれか、クエリを付けられるように拡張するか。