ポケコロツインのアセット破損対策について

お疲れ様です。ポケコロツインクライアントエンジニアのSです。
今回はUnityアセットの管理周りについて書きたいと思います。
(本記事はAdressableを使用しないことを想定しています)

アセット破損状態チェック

アセットバンドルのファイルサイズが大きい場合、ネットワーク環境によって途中でダウンロードが停止することがあります。
そのネットワーク環境の影響で、ファイルが破損する可能性があります。
例えば、

① 一部のプレハブのテクスチャーが表示されない(黒い四角いなど)
② 完全に破損ファイルになる

 
①の場合はロードしてもクラッシュにならないですが、表示面だけはおかしくなります。ですが、②のケースでは、AssetBundleのLoadFromFileAsyncを使用し、Try-Catchの中に入れてもアプリがクラッシュしてしまいます。

どのような対策にしましたか?

まずは、アセットロード前にアセットが破損するかどうかチェックを入れてみました。
AssetBundleの状態チェックなどのAPIがないため、ロードせずにアセットが破損するかどうかのチェックができなさそうです。
ですが、LoadFromFileAsyncなどにCRCという値を渡せばファイルが保存されるかどうかのチェックができるようになります。そのLoadFromFileAsyncをTry-catchの間に入れると、catchでファイルがnullか等をチェックする事が可能となるため、色々対策できるようになります。例えば、もう一度ファイルをダウンロードし直すなど。
(ちなみに、Addressableを使ったらそのままCRCのチェックボックスをチェックするだけでも大丈夫そうです)

では、CRCというものとはなんでしょう?

CRCというのは、「巡回冗長検査」(Cyclic Redundancy Check)というものです。要するに、誤り検出符号の一種ということです。
 
CRCの値は、アセットバンドルをビルドしたときにBuildPipeline.GetCRCForAssetBundleという関数から取得できます。ファイルをロードする際にそのCRCを用いることで、アセット破損の状況を感知することができますので、ぜひ試してみてください。

アセットファイルの検知

そもそも、1つのアセットバンドルのファイルサイズは大きくしたくないですね。
ということで、今回はS3にアップされたファイルのサイズを感知し、一定のサイズを超えるファイルがアップロードされたときにSlackに通知する仕組みを作ってみたいと思います。今回は、S3のLambda機能を使ってみました。

まずは、新しいLambda関数を作りましょう

作成後、トリガーを設定します。ざっくりこんな感じで設定しました。
イベントタイプ → s3:ObjectCreated
バケット → 監視したいバケットのパス
プレフィックス → バケットのなかでも特にこのフォルダーだけ!とかありましたら指定します。例えば Test/TestFolder2/ など。
 
上記のように設定すれば、「Test/TestFolder2」にファイルがアップされるたびにLambdaの関数が呼ばれるようになります。
 
関数のセットアップが終われば、関数の部分を見ていきましょう。
まずは、アップされたファイルサイズを取得する方法について書きます。デフォルトの関数で下記のようなものが用意されるかと思います。

exports.handler = function (event, context) {

};

次に、event.Recordsでobjectのサイズを取得します。例えば、下記のコードはファイルサイズが5MB以上かどうかチェックするコードです。

exports.handler = function (event, context) {
   event.Records.forEach(record =>
   {
       if (record.s3.object.size > 5000000)
       {
           // 5MB以上
       }
   });
};
 
そして、Slackに追加する方法ですが、まずは希望のチャンネルにWebhookというアプリを追加する必要があります。webhookを設定後、APIのURLが発行されると思いますので、そのリンクを使って希望のSlackチャンネルにメッセージを送信します。

const slack_url = 'https://hooks.slack.com/services/test/test2/test3'; // ここをが実際のwebhookからのURLに変更
const slack_req_opts = url.parse(slack_url);
slack_req_opts.method = 'POST';
slack_req_opts.headers = {'Content-Type': 'application/json'};
exports.handler = function (event, context) {
   event.Records.forEach(record =>
   {
       if (record.s3.object.size > 5000000)
       {
           // 5MB以上
           // リクエストを作成
           var req = https.request(slack_req_opts, function (res) {
               if (res.statusCode === 200) {
                 // 成功
               } else {
                 // 失敗したので、res.statusCodeなどをみてたらコードをチェックしましょう
               }
           });
            
           // エラーメッセージ
           req.on('error', function(e) {
               console.log(e.message);
           });
            
           // record.s3.object.keyでアップされたもののパスを取得できる
           var str = "ファイルはサイズオーバー!" + record.s3.object.key;
           req.write(JSON.stringify({
               text: str,
               icon_emoji : ":exclamation:",
           }));
           req.end();
       }
   });
};

上記のコードで5MB以上のファイルが特定のバケットにアップされたら通知がきます。
Slackの絵文字などいろいろメッセージをカスタマイズできますので是非試してみてください。
 

まとめ

通信環境によってアセットが破損状態になる可能性がありますので、対策としては、

① CRCチェックをやる
② 1つのファイルのサイズをできるだけ小さくする

ということです。
 

 


 

ココネでは一緒に働く仲間を募集中です。

ご興味のある方は、ぜひこちらの採用特設サイトをご覧ください。

https://www.cocone.co.jp/recruit/contents/

 

Category

Tag

%d人のブロガーが「いいね」をつけました。