AWS
S3
Unity
cognito

UnityのGameObjectにAWS S3にある画像をテクスチャとして貼り付けたい話

はじめに

〜AWSさんに届け〜
S3のサンプルに画像を扱うものもあるとヒヨコには嬉しいです。ぐぐると探している人もいるようでした。

日本語でドンピシャな情報にたどり着けなかったのでメモっておきます。
UnityのテクスチャにAWSの画像を使いたい話です。

3行で要点だけ欲しい人向け情報

  1. SDKをダウンロードしてきてUnityにインポート
  2. AWS側の準備する(S3,Cognito,Cognito用IAMロール)
  3. サンプルを修正して(サンプルだと文字の読み取りなので画像の処理に変更して)動かす

やったこと詳細

環境

  • Unity 2017.3.1f1(64bit)
  • Mac利用

SDKをダウンロード&インポート

AWS側の準備する

S3の準備

  • bucketを用意する
  • 適当な画像ファイル(自分はPNGを利用しました)をアップロードしておく
  • bucket名、ファイル名はあとで使います

Cognitoの設定(IAMロールの設定)

  • Manage Federated Identitiesから新規で作成
  • IAM ROLEを設定、S3の必要な権限を追加しておく(ひとまず試したいのであればS3FullAccessをくっつけておくと間違いないはず)

Unityに準備したAWSの情報をいれていく

  • サンプルの Assets/Exapmles/S3Example を開いて編集していく
  • S3というGameObjectがHierarchy内にあるので、選択してInspectorタブでS3 Example(Script)を見つけて先ほど作ったS3とCognitoの情報を入れ込む
    • Tokyoリージョンはap-northeast-1デスヨ

サンプルを修正して動かす

とりあえず、疎通確認する

  • サンプルなのでそのまま動くだろうと安易にPlayしてみましょう。そして、画像を取ってくるのが目標なので、Get Objectをポチる。自分はここが動きませんでした:frowning2:
  • 動かない理由が自分と同じInvalidOperationException: Cannot override system-specified headers UnityEngine.Networking.UnityWebRequest.SetRequestHeader (System.String name, System.String value) (at /Users/builduser/buildslave/unity/build/Modules/UnityWebRequest/Public/UnityWebRequest.bindings.cs:424) ...であれば、Start関数内を以下を参考に修正してください(2行目が追加されています)
S3Example.cs
        void Start()
        {
            UnityInitializer.AttachToGameObject(this.gameObject);
            AWSConfigs.HttpClient = AWSConfigs.HttpClientOption.UnityWebRequest; //added
            GetBucketListButton.onClick.AddListener(() => { GetBucketList(); });
            PostBucketButton.onClick.AddListener(() => { PostObject(); });
            GetObjectsListButton.onClick.AddListener(() => { GetObjects(); });
            DeleteObjectButton.onClick.AddListener(() => { DeleteObject(); });
            GetObjectButton.onClick.AddListener(() => { GetObject(); });
        }
  • 再トライ。エラーが出ずに、ファイル名が表示されるようになればOKです。別のエラーなどは、AMIロールの権限かbucket名、ファイル名を確認してみてください

GetObjectのところを画像を取得して貼り替えるものに変更する

  • ソースコードを以下のとおり変更
S3Example.cs
public GameObject imagebox = null; // added 画像を貼り付けるオブジェクトとして利用

private void GetObject()
{
    Client.GetObjectAsync(S3BucketName, SampleFileName, (responseObj) =>
        {
            MemoryStream stream = new MemoryStream();
            responseObj.Response.ResponseStream.CopyTo(stream);
            Texture2D tex = new Texture2D(4, 4);
            byte[] results = stream.ToArray();
            tex.LoadImage(results);
            imagebox.GetComponent<Renderer>().material.mainTexture = tex;        
        }
    );
}
  • 保存するとCopyToのところでAssets/Examples/S3Example.cs(130,49): error CS1061: TypeSystem.IO.Stream' does not contain a definition for CopyTo' and no extension methodCopyTo' of type System.IO.Stream' could be found. Are you missing an assembly reference?がでますが、今回は設定を変更して回避
    • Edit > Project Settings > Player で、Other Settings内のConfigurationのScripting Runtime VersionをExperimental(.NET 4.6 Equivalent)に変更して再起動
  • Hierarchy内に適当なCubeなどのオブジェクトを追加
    • S3オブジェクトのスクリプトで追加したimageboxに紐付け
  • 実行。GetObjectのボタンを押すと、ログのところを消してしまったので、Game画面上は変化ないですが、SceneビューのCubeに画像が貼り付けられます

オワリ

Windowsでも動きました。回り道してたので、なにかもっとズバッといけるところあれば教えてください・・・