AWS DynamoDBとは?
AWSのサービスに含まれている、KVS(キーバリューストア)と呼ばれるデータをキーの集合体として保存していくNoSQLデータベース。今回試したこと
Unityから、DynamoDBにあらかじめ決まっているIDにアクセスしそこから画像URLを受け取りUnity側に画像を表示させる。主な手順は、こちらの記事を参考にさせて頂きました。
手順
ここでは、アカウントがあるものとし手順2から説明をしていきます。S3バケットに画像をアップロード
S3バケットの作成
お好きなバケット名を入力し、お好きなAWSリージョンを設定します。リージョンの地域設定は右上[グローバル]から設定を変更できます。
次に[このバケットのブロックパブリックアクセス設定]の、[パブリックアクセスを全てブロック]のチェックを外し、下の警告のチェックボックスにチェックを入れます。
上記が完了したら、ページ下部にある[バケットを作成]を押して下さい。
パブリックの設定
作成されたバケットは最初のバケットメニューに先ほど付けた名前のバケット(私の場合tipsbacket)が表示されます。
名前の部分をクリックしバケット毎の設定メニューに移動します。
移動が完了したら、[アクセス許可]を選択し下の[バケットポリシー]の[編集]を押します。
下記のコードをポリシーに書き込み[変更の保存]をします。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::作成したバケットの名前/*"
}
]
}
画像のアップロード
ポリシーの変更が保存出来たら、先ほどのバケット毎の設定の[オブジェクト]を選択し、[アップロード]を押すか、アップロードしたいものをこの画面でドラッグ&ドロップすることでアップロード確認画面へ移動します。
先ほど、ドラッグ&ドロップで移動した人は[ファイルとフォルダ]には選択したものが表示されています。この画面からアップロードする場合は、[ファイルの追加][フォルダの追加]または、ドラッグ&ドロップで選択できます。アップロードしたいものを選択し終えたら[アップロード]を押します。
アップロードが完了したら、オブジェクトメニューにアップロードしたものの名前が表示されているのでクリックします。
下記画像のような画面が表示されたら、右下オブジェクトURLをクリックします。
アップロードしたものが表示されたら成功です。
以上で、S3については終了です。
DynamoDBでテーブルを作成
サービスからDynamoDBを検索し、さっそく[テーブルの作成]をしていきましょう。
お好きな[テーブル名]と、[パーテンションキー]の名前を決めます。
[パーテンションキー]は項目検索の際に必ず必要なので、今回は分かりやすく「ID」と入力しましょう。
[ソフトキー]とその他の設定は今回は使用しないのでそのままにして、ページ下の[テーブルの作成]を押してください。
テーブルの作成が出来たら、左のDynamoDBメニューの[テーブル]→[項目の探索]を選択します。
下記の画像の様な画面になったら、[返された項目]にある[項目を作成]を押します。
そうしたら、[パーテンションキー]であるIDを[値]に入力。数字で1~入力すると後から楽です。
その後[新しい属性の追加]から文字列を選択し、[属性名]を「URL」、[値]に先ほどS3にアップロードしたもののURLを入力して、[項目を作成]を押してください。
DynamoDBでのテーブル作成は以上です。
Lambda関数を作成
IAMでロールの作成
まずは、LambdaがDynamoDBにアクセスできるようにロールを設定します。
サービスからIAMを検索します。
AIMの左のメニューから[アクセス管理]→[ロール]を選択し、[ロールを作成]を押します。
画面が移動したら、エンティティタイプを[AWSのサービス]、ユースケースを[Lambda]を選択して[次へ]を押してください。
次に、許可ポリシーを選択します。
[CloudWatchFullAccess]と[AmazonDynamoDBFullAccess]にチェックを入れ[次へ]を押します。似た項目が多いので検索をかけるとより早く見つかります。
最後にロールの名前を決めてページ下部の[ロールを作成]から作成を完了してください。
Lambdaの作成、設定
サービスからLambdaを検索します。
Lambdaのメニューが開けたら、[関数の作成]を押します。
関数の作成で、[一から作成]を選択し、お好きな[関数名]を入力します。
[ランタイム]は今回、「Node.js 16.x」を使用します。
これらを選択したら[関数の作成]を押します。
関数の作成が終って開かれるメニューに[コード]というものがあるのでそれを選択し下記のコードを記入し、[Test]の横にある[Deploy]を押し変更を保存します。
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]を押して変更を保存が確認出来たら。[コード]と同じメニュー欄にある[設定]を選択して、[アクセス権限]を選択します。
アクセス権限のメニューから[実行ロール]の[編集]を押してください。
画像のような画面が出たら、[既存のロール]から先ほど作成したロールを選択し[保存]してください。[説明]は任意で入力してもいいです。
Lambdaの設定は以上です。
APIゲートウェイを作成,Lambdaとリンク
サービスからAPI Gatewayを検索し、画像の様な画面が出たら[APIを作成]を押します。
次の画面で、画面下部の[REST API]の[構築]を押してください。
その次の画面では、[API name]を入力して[create API]を押してください。
[Description]は任意で入力してください。
APIが作成されたら、[Actions]の中から[Create Method]を選択し、現れた空白のプルダウンメニューから[POST]を選択してチェックマークを押してください。
そうすると右に画像の様なメニューが表示されるので、[Lambda Function]の欄に先ほど作成したLambda関数の名前を入力して[Save]を押してください。Lambdaに権限を追加するかを聞かれるので[OK]を押します。
次に[Actions]から、[Enable CORS]を選択します。選択すると右側にメニューが表示されるので、そのまま[Enable CORS and replace CORS headers]を押します。そうすると、メソッドの変更の確認をしてくるので、[Yes,replace existing values]を押します。
メソッドの変更が完了したら、再び[Actions]を開き[Deploy API]を選択します。
ポップアップ表示されたメニューの[Deployment stage]で[New Stage]を選択し、[Stage name]にお好きな名前を付けて[Deploy]を押します。
デプロイが終わると、APIゲートウェイに接続するために必要な「Invoke URL」が表示されるのでこれをUnityで使います。
AWSでのあれこれはこれで終了です。
Unityで画像を出す
Unityでプロジェクトを作成し以下の準備します。
- Rawimageの作成
- 空のオブジェクトの作成
- C#スクリプトを2つ作成
私は、画像を表示させるものをManager.cs
APIゲートウェイにアクセスするものをUnitytoaws.cstとしました。
スクリプトはこちらです。
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();
}
}
}
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をドラッグ&ドロップしコンポーネントを追加します。
次に空のオブジェクトにUnitytoaws.csをドラッグ&ドロップしコンポーネントを追加します。そして、インスペクターの[ID]にDynamoDBから取り出したい項目のIDを入力します。
実行すると、UnityがAPIゲートウェイへアクセスし、それをトリガーとしたLambdaが動きDynamoDBからURLを取得しそのURLでS3に保存されている画像を表示することが出来ました!!
Git:https://github.com/nkc20206082/AWSTest.git