2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Unity:AWSDynamoDBから情報を貰う

Last updated at Posted at 2023-03-08

AWS DynamoDBとは?

AWSのサービスに含まれている、KVS(キーバリューストア)と呼ばれるデータをキーの集合体として保存していくNoSQLデータベース。

今回試したこと

Unityから、DynamoDBにあらかじめ決まっているIDにアクセスしそこから画像URLを受け取りUnity側に画像を表示させる。
主な手順は、こちらの記事を参考にさせて頂きました。

手順

  1. AWSアカウント作成
  2. S3バケットに画像をアップロード
  3. DynamoDBでテーブルを作成
  4. Lambda関数を作成
  5. APIゲートウェイを作成,Lambdaとリンク
  6. Unityで画像を出す
ここでは、アカウントがあるものとし手順2から説明をしていきます。

S3バケットに画像をアップロード

S3バケットの作成

サービスからS3を検索します。
キャプチャ.JPG

S3のバケットを選択し、[バケットを作成]を押します。
キャプチャ2.JPG

お好きなバケット名を入力し、お好きなAWSリージョンを設定します。リージョンの地域設定は右上[グローバル]から設定を変更できます。
キャプチャ3.JPG

次に[このバケットのブロックパブリックアクセス設定]の、[パブリックアクセスを全てブロック]のチェックを外し、下の警告のチェックボックスにチェックを入れます。
キャプチャ4.JPG

上記が完了したら、ページ下部にある[バケットを作成]を押して下さい。

パブリックの設定

作成されたバケットは最初のバケットメニューに先ほど付けた名前のバケット(私の場合tipsbacket)が表示されます。
名前の部分をクリックしバケット毎の設定メニューに移動します。
キャプチャ5.JPG

移動が完了したら、[アクセス許可]を選択し下の[バケットポリシー]の[編集]を押します。
キャプチャ6.JPG

下記のコードをポリシーに書き込み[変更の保存]をします。

ポリシー
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "PublicReadGetObject",
			"Effect": "Allow",
			"Principal": "*",
			"Action": "s3:GetObject",
			"Resource": "arn:aws:s3:::作成したバケットの名前/*"
		}
	]
}

キャプチャ7.JPG

画像のアップロード

ポリシーの変更が保存出来たら、先ほどのバケット毎の設定の[オブジェクト]を選択し、[アップロード]を押すか、アップロードしたいものをこの画面でドラッグ&ドロップすることでアップロード確認画面へ移動します。
キャプチャ8.JPG

先ほど、ドラッグ&ドロップで移動した人は[ファイルとフォルダ]には選択したものが表示されています。この画面からアップロードする場合は、[ファイルの追加][フォルダの追加]または、ドラッグ&ドロップで選択できます。アップロードしたいものを選択し終えたら[アップロード]を押します。
キャプチャ9.JPG

アップロードが完了したら、オブジェクトメニューにアップロードしたものの名前が表示されているのでクリックします。
下記画像のような画面が表示されたら、右下オブジェクトURLをクリックします。
アップロードしたものが表示されたら成功です。
キャプチャ10.JPG
キャプチャ11.JPG

以上で、S3については終了です。

DynamoDBでテーブルを作成

サービスからDynamoDBを検索し、さっそく[テーブルの作成]をしていきましょう。
キャプチャ12.JPG

お好きな[テーブル名]と、[パーテンションキー]の名前を決めます。
[パーテンションキー]は項目検索の際に必ず必要なので、今回は分かりやすく「ID」と入力しましょう。
[ソフトキー]とその他の設定は今回は使用しないのでそのままにして、ページ下の[テーブルの作成]を押してください。
キャプチャ13.JPG

テーブルの作成が出来たら、左のDynamoDBメニューの[テーブル]→[項目の探索]を選択します。
下記の画像の様な画面になったら、[返された項目]にある[項目を作成]を押します。
キャプチャ14.JPG

そうしたら、[パーテンションキー]であるIDを[値]に入力。数字で1~入力すると後から楽です。
その後[新しい属性の追加]から文字列を選択し、[属性名]を「URL」、[値]に先ほどS3にアップロードしたもののURLを入力して、[項目を作成]を押してください。
キャプチャ15.JPG

項目が追加されていたら成功です。
キャプチャ16.JPG

DynamoDBでのテーブル作成は以上です。

Lambda関数を作成

IAMでロールの作成

まずは、LambdaがDynamoDBにアクセスできるようにロールを設定します。
サービスからIAMを検索します。
AIMの左のメニューから[アクセス管理]→[ロール]を選択し、[ロールを作成]を押します。
キャプチャ17.JPG

画面が移動したら、エンティティタイプを[AWSのサービス]、ユースケースを[Lambda]を選択して[次へ]を押してください。
キャプチャ18.JPG

次に、許可ポリシーを選択します。
[CloudWatchFullAccess]と[AmazonDynamoDBFullAccess]にチェックを入れ[次へ]を押します。似た項目が多いので検索をかけるとより早く見つかります。
キャプチャ19.JPG
キャプチャ20.JPG

最後にロールの名前を決めてページ下部の[ロールを作成]から作成を完了してください。
キャプチャ21.JPG

Lambdaの作成、設定

サービスからLambdaを検索します。
Lambdaのメニューが開けたら、[関数の作成]を押します。
キャプチャ22.JPG

関数の作成で、[一から作成]を選択し、お好きな[関数名]を入力します。
[ランタイム]は今回、「Node.js 16.x」を使用します。
これらを選択したら[関数の作成]を押します。
キャプチャ23.JPG

関数の作成が終って開かれるメニューに[コード]というものがあるのでそれを選択し下記のコードを記入し、[Test]の横にある[Deploy]を押し変更を保存します。
キャプチャ24.JPG

index.js
const AWS = require('aws-sdk')
const client = new AWS.DynamoDB.DocumentClient()

/**
 * API Gatewayを通してリクエストから受け取ったIDと一致するitemを取得して返却するLambda
 * 
 * @param {*} event APIGatwayからわたってくるパラメーターがこのevent引数を通して渡される
 * GETリクエストにおけるクエリはqueryStringParametersというプロパティに設定されている
 * @returns 
 */
exports.handler = async (event)=>{

    console.log("event", event);
    const ID = event.Keys.ID;

    /**
     * ハッシュキー:IDというDynamoDBテーブルを想定
     */
    const result = await client.query({
        TableName:'TestDB',//テーブル名
        KeyConditionExpression:'#ID = :ID',
        ExpressionAttributeNames:{
            '#ID':'ID'
        },
        ExpressionAttributeValues:{
            ':ID':ID
        }
    }).promise()


    const items = result.Items

    return {
        statusCode:200,
        body:items
    }
    
}

[Deploy]を押して変更を保存が確認出来たら。[コード]と同じメニュー欄にある[設定]を選択して、[アクセス権限]を選択します。
アクセス権限のメニューから[実行ロール]の[編集]を押してください。
キャプチャ25.JPG

画像のような画面が出たら、[既存のロール]から先ほど作成したロールを選択し[保存]してください。[説明]は任意で入力してもいいです。
キャプチャ26.JPG

Lambdaの設定は以上です。

APIゲートウェイを作成,Lambdaとリンク

サービスからAPI Gatewayを検索し、画像の様な画面が出たら[APIを作成]を押します。
キャプチャ27.JPG

次の画面で、画面下部の[REST API]の[構築]を押してください。
キャプチャ28.JPG

その次の画面では、[API name]を入力して[create API]を押してください。
[Description]は任意で入力してください。
キャプチャ29.JPG

APIが作成されたら、[Actions]の中から[Create Method]を選択し、現れた空白のプルダウンメニューから[POST]を選択してチェックマークを押してください。
キャプチャ30.JPG
キャプチャ31.JPG

そうすると右に画像の様なメニューが表示されるので、[Lambda Function]の欄に先ほど作成したLambda関数の名前を入力して[Save]を押してください。Lambdaに権限を追加するかを聞かれるので[OK]を押します。
キャプチャ32.JPG
キャプチャ33.JPG

次に[Actions]から、[Enable CORS]を選択します。選択すると右側にメニューが表示されるので、そのまま[Enable CORS and replace CORS headers]を押します。そうすると、メソッドの変更の確認をしてくるので、[Yes,replace existing values]を押します。
キャプチャ34.JPG
キャプチャ35.JPG
キャプチャ36.JPG

メソッドの変更が完了したら、再び[Actions]を開き[Deploy API]を選択します。
ポップアップ表示されたメニューの[Deployment stage]で[New Stage]を選択し、[Stage name]にお好きな名前を付けて[Deploy]を押します。
キャプチャ37.JPG
キャプチャ38.JPG

デプロイが終わると、APIゲートウェイに接続するために必要な「Invoke URL」が表示されるのでこれをUnityで使います。
キャプチャ39.JPG

AWSでのあれこれはこれで終了です。

Unityで画像を出す

Unityでプロジェクトを作成し以下の準備します。

  • Rawimageの作成
  • 空のオブジェクトの作成
  • C#スクリプトを2つ作成
  • 私は、画像を表示させるものをManager.cs
    APIゲートウェイにアクセスするものをUnitytoaws.cstとしました。

    スクリプトはこちらです。

Manager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;

public class Manager : MonoBehaviour
{
    public List<string> URLs = new List<string>();
    [SerializeField] private RawImage _image;

    [System.Obsolete]
    public IEnumerator  Indicate()
    {
        UnityWebRequest www = UnityWebRequestTexture.GetTexture(URLs[0]);

        //画像を取得できるまで待つ
        yield return www.SendWebRequest();

        if (www.isNetworkError || www.isHttpError)
        {
            Debug.Log(www.error);
        }
        else
        {
            //取得した画像のテクスチャをRawImageのテクスチャに張り付ける
            _image.texture = ((DownloadHandlerTexture)www.downloadHandler).texture;
            _image.SetNativeSize();
        }
    }
}

Unitytoaws.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
public class Unitytoaws : MonoBehaviour
{
    [SerializeField] private string ID;//欲しい情報のID
    [SerializeField] private DynamoResponse response;//返ってきたものを表示する
    [SerializeField] Manager Manager;

    public string URL;//URLを入れるよう

    [Serializable]
    public class DynamoIftest
    {
        public DynamoQueryKey Keys;
        [Serializable]
        public class DynamoQueryKey
        {
            public string ID;//クエリに使うキー
        }
    }

    [Serializable]
    public class DynamoResponse
    {
        public List<DynamoResponseItems> body;
        [Serializable]
        public class DynamoResponseItems
        {
            public string ID;//取得ID
            public string URL;//取得URL
        }
    }

    [Obsolete]
    void Start()
    {
        StartCoroutine(AwsApiTest());
    }

    [Obsolete]
    private IEnumerator AwsApiTest()
    {
        var awsElement = new DynamoIftest()
        {
            Keys = new DynamoIftest.DynamoQueryKey() { ID = ID}
        };
        string jsonStr = JsonUtility.ToJson(awsElement);

        var request = new UnityWebRequest();

        request.url = "APIゲートウェイの";//APIゲートウェイとの通信
        var body = Encoding.UTF8.GetBytes(jsonStr);
        request.uploadHandler = new UploadHandlerRaw(body);
        request.downloadHandler = new DownloadHandlerBuffer();

        request.SetRequestHeader("Content-Type", "application/json");
        request.method = UnityWebRequest.kHttpVerbPOST;
        yield return request.Send();

        if (request.isNetworkError)
        {
            Debug.Log(request.error);
        }
        else
        {
            if (request.responseCode == 200)
            {
                var responseJsonText = request.downloadHandler.text;
                Debug.Log(responseJsonText);
                response = JsonUtility.FromJson<DynamoResponse>(responseJsonText);
                Debug.Log(response.body[0].URL);
                URL = response.body[0].URL;

                Manager.URLs.Clear();
                foreach (var item in response.body)
                {
                    Manager.URLs.Add(item.URL);
                }
                Manager.StartCoroutine("Indicate");
            }
            else
            {
                Debug.Log("failed");
            }
        }
    }
}

スクリプトが書けたら、RawimageにManaget.csをドラッグ&ドロップしコンポーネントを追加します。
キャプチャ40.JPG

次に空のオブジェクトにUnitytoaws.csをドラッグ&ドロップしコンポーネントを追加します。そして、インスペクターの[ID]にDynamoDBから取り出したい項目のIDを入力します。
キャプチャ41.JPG

実行すると、UnityがAPIゲートウェイへアクセスし、それをトリガーとしたLambdaが動きDynamoDBからURLを取得しそのURLでS3に保存されている画像を表示することが出来ました!!
キャプチャ42.JPG

Git:https://github.com/nkc20206082/AWSTest.git

今回のまとめ

今回、AWSを全く知らない私がネットの記事を参考にしつつここまで作るとが出来ました。最初は、AWSでサーバーを借りてPHPを使ってMySQLでやろうと思っていたことが直ぐに出来る便利なサービスだと思いました。しかし、DynamoDBはKVSを特徴とするDBだった為自分の知識にあるものと相違があり思ったような実装も難しいことが分かりました。 しかし、今回初めてNoSQLなDBを触って複雑ではない情報を扱う場合こちらの方が使いやすいことは理解しました。 次は、こちらも途中で断念したAWSでサーバーを借りDockerを構築してPHPの実行環境を作ることをやっていきたいと思います。
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?