2
Help us understand the problem. What are the problem?

posted at

UnityでLambdaを介してDynamoDBにアクセスするAPI連携を実装する方法

今回実装したこと

Unity ⇆ API gateway ⇆ Lambda ⇆ DynamoDB ⇆ S3
S3上に置いた画像データをおき、そこに至るパスをDynamoDB上にストックし、Unityからの入力をキッカケにAPI gatewayを経由してLambdaを起動して、入力情報に応じてDynamoDBから必要なS3のパスを返す実装を完成しました。
文字だけだと呪文にしか聞こえないので、実際に動いているところを共有します。

UnityでAWSのサービスを使用する場合、余計なSDKやプラグインなどを使用せず、あくまでAWSのサービスのみで完結する方法についてまとめました。
これができれば、フロントサイドは別にUnityじゃなくてもさまざまなサービスを利用することが可能です。

注意点

AWSの使用は従量課金制となりますので、ここから先を進んだ場合に使用量が発生する可能性があります。そのため、ここから先に進んで費用が発生しても自己責任でお願いいたします。

AWS側の設定

AWSへのログイン

他の記事やgoogleで検索し、AWSのコンソール画面まで進んでください。
Image from Gyazo

S3の設定

まずは、動画ファイルを置いておく場所をS3上に作成します。

バケットの作成

下記の画像を参考に、今回使用する化と作成します。
Image from Gyazo

Image from Gyazo

Image from Gyazo

Image from Gyazo

バケットパブリック設定

個別のURLを叩くだけで動画が見られるようにするために、下記のように設定しパブリックアクセスを許可します。
Image from Gyazo

Image from Gyazo

Image from Gyazo

バケットポリシーの部分に下記のスクリプトを貼り付けます。
スクリプト内の'bucket name'は今回作成したバケット名に変更してください。

Image from Gyazo

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::<bucket nameを入れてください>/*"
            ]
        }
    ]
}

動画のアップロード

下記を参考に、自身の動画をアップロードしていきます。
Image from Gyazo

Image from Gyazo

作成されたURLをコピーして、

Image from Gyazo

ブラウザに貼り付けると…、

Image from Gyazo

無事に動画が流れます。

DynamoDBの設定

続いて、先ほど作成した動画につながるS3のURLをためておくデータベースをDynamoDBに作成します。

テーブルの作成

DynamoDBでは作成するデータベースをテーブルと呼びます。
下記の画像を参考にテーブルを作成します。

Image from Gyazo

Image from Gyazo

Image from Gyazo

データの更新方法

下記の手順でノーコードでDynamoDB上のデータの更新・登録が可能です。

Image from Gyazo

Image from Gyazo

Image from Gyazo

ちなみに今回は、下記のように設定しました。
Image from Gyazo

Lambdaの設定

次に、DynamoDBからデータを引き出すために、Lambdaというサービス上に関数を作成し、UnityからLambdaに刺激が入ると関数が起動するように設定を行います。

IAMの設定

まず初めに、LamdbaがDynamoDBの内容にアクセスできるようにIAMで権限を設定します。
下記を参考にDynamoDBとCloudWatchのFullAccessのポリシーを持つロールを作成してください。
Image from Gyazo

Image from Gyazo

Image from Gyazo

Image from Gyazo

Image from Gyazo

Image from Gyazo

Lambdaの設定

Lambdaに移動して関数を作成します。

Image from Gyazo

今回は、Node.jsで関数を作成します。
Image from Gyazo

コードソースのindex.jsの部分に下記のコードを貼り付け、Deployを押します。
Image from Gyazo

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

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

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

    /**
     * ハッシュキー:userId、ソートキー:movieIdというDynamoDBテーブルを想定している
     */
    const result = await client.query({
        TableName:'MoviesDB',
        KeyConditionExpression:'#DoctorID = :DoctorID AND begins_with(#MovieID , :MovieID)',
        ExpressionAttributeNames:{
            '#DoctorID':'DoctorID',
            '#MovieID':'MovieID'

        },
        ExpressionAttributeValues:{
            ':DoctorID':DoctorID,
            ':MovieID':MovieID,
        }
    }).promise()


    const items = result.Items

    return {
        statusCode:200,
        body:items
    }
    
}

ロールの設定

Image from Gyazo

名前は適宜設定し、ロール部分に先ほど作成したロールを割り当てます。
Image from Gyazo

API Gatewayの設定

最後に、Unityからの刺激をLambdaに伝える通り道であるAPIをAPI Gatewayで作成します。

APIの作成

下記の図を参考にAPIを作成します。

Image from Gyazo

今回はREST APIを作成します。

Image from Gyazo

名前を適当に設定しAPIを作成する
Image from Gyazo

Image from Gyazo

Image from Gyazo

Image from Gyazo

Image from Gyazo

Image from Gyazo

Image from Gyazo

Image from Gyazo

Image from Gyazo

Image from Gyazo

Image from Gyazo

Image from Gyazo

APIの完成
Image from Gyazo

Unity側の設定

最後にUnity側から動画を呼び出す設定を行います。

動画を映す板の作成

動画のはめ込みに関しては他の記事に譲ります。
流れは以下の通りです。
① 3D planeを作成
② videoplayerのオブジェクトを作成
③ render textureを作成
④ materialを作成
⑤ 作成したmaterialに作成したrender textureをアタッチ
⑥ 3D planeにmaterialをアタッチ
⑦ videoplayerコンポーネントにrender textureをアタッチ

VideoPlayerのスクリプト

下記のスクリプトをVideoPlayerオブジェクトにアタッチします。

VideoplayerManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Video;

public class VideoPlayerManager : MonoBehaviour
{
    VideoPlayer video;
    public List<string> URLs = new List<string>();

    public void VideoPlay(int num)
    {
        video = gameObject.GetComponent<VideoPlayer>();
        video.playOnAwake = false;
        video.waitForFirstFrame = true;
        video.source = VideoSource.Url;
        video.url = URLs[num];

        video.prepareCompleted += VideoPlayerOnPrepareCompleted;
        video.Prepare();
    }

    private void VideoPlayerOnPrepareCompleted(VideoPlayer source)
    {
        video.Play();
    }

    public void OnClickVideoPlay(int num)
    {
        VideoPlay(num);
    }
}

AWSに接続するための設定

下記のスクリプトをからのオブジェクトにアタッチします。

unitytoaws
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Serialization;
using UnityEngine.UI;
public class unitytoaws : MonoBehaviour
{
    [SerializeField] private string DoctorID;
    [SerializeField] private string MovieID;
    [SerializeField] private DynamoResponse response;
    [SerializeField] VideoPlayerManager videoPlayerManager;

    public string URL;

    [Serializable]
    public class DynamoIftest
    {
        public DynamoQueryKey Keys;
        [Serializable]
        public class DynamoQueryKey
        {
            public string DoctorID;
            public string MovieID;
        }
    }

    [Serializable]
    public class DynamoResponse
    {
        public List<DynamoResponseItems> body;
        [Serializable]
        public class DynamoResponseItems
        {
            public string DoctorID;
            public string MovieID;
            public string URL;
        }
    }
    void Start()
    {
        StartCoroutine(AwsApiTest());
    }

    private IEnumerator AwsApiTest()
    {
        var awsElement = new DynamoIftest()
        {
            Keys = new DynamoIftest.DynamoQueryKey() { DoctorID = DoctorID, MovieID = MovieID }
        };
        string jsonStr = JsonUtility.ToJson(awsElement);

        var request = new UnityWebRequest();

        request.url = "<ApiGatewayで作成したApiのUrl>";
        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;

                videoPlayerManager.URLs.Clear();
                foreach (var item in response.body)
                {
                    videoPlayerManager.URLs.Add(item.URL);
                }

            }
            else
            {
                Debug.Log("failed");
            }
        }
    }
}

完成形

完成した挙動がこちらです。

今後もSDKを使用せずに、APIでUnityからAWSを使える実装の勉強を進めていきます。

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
2
Help us understand the problem. What are the problem?