2021年11月18日

[Unity] AWSの最新版SDKはUnityプラグインではなく、.NETだった件

前回の記事で、iOS用のAWSのSDKの最新版はCocoaPodsを利用することで使用できました。
でも、Unity用のAWSのSDKについては、そう簡単にはいきませんでした。
Unity用パッケージではなく、.NETで公開されている方が最新版だとわかったのです。

結論としては対応できたのですが、その過程がめっちゃ苦労したのでメモとして残しておきます。


■ 概要
@ AWS SDKの最新版は .NET。Unity用プラグイン(.unitypackage)の更新は既に終了している
A DLLは複数あるけど、.NET Standard 2.0版 を使用する(たぶん)
B SDKの圧縮ファイル(.nupkg)は、MacではWクリックでは解凍できない
C メソッド定義が重複するので、新旧のDLLは共存させない
D メソッドが非同期用になっていたので、Taskで対応


@ AWS SDKの最新版は .NET。Unity用プラグイン(.unitypackage)の更新は既に終了している


きっかけは、数消しパズル(Android版)の更新に着手した時でした。
iOS版がスムーズに作業できたので、Android版もそうだろうと思っていたら、ビルドエラーが出ました↓


Error Unity ArgumentException: Object of type 'System.Object[]' cannot be converted to type 'UnityEngine.AndroidJavaObject[]'.
2021/11/17 21:45:48.606 23782 23813 Error Unity at System.RuntimeType.CheckValue (System.Object value, System.Reflection.Binder binder, System.Globalization.CultureInfo culture, System.Reflection.BindingFlags invokeAttr) [0x00000] in <00000000000000000000000000000000>:0
...


調べてみると、Unity2019からAndroidで動作しないという声があったようです。

AWS SDK for Unity を利用したアプリがAndroid上で動作しない【Unity 2019 2.11f1】:
https://qiita.com/kosuke1113/items/904df92d444804d496c3

AWS SDKをUnity(2018.1以降)で使う:
https://qiita.com/nshinya/items/0a71d4658e7f4a650844

ではどこから最新版のSDKをダウンロードしようというと、NuGetという所から落とせるらしい。

Obtaining assemblies for the AWS SDK for .NET:
https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/net-dg-obtain-assemblies.html

上記ページにある「aws-sdk-netstandard2.0.zip」のリンクからZipファイルを落とします。
(他にも、aws-sdk-net45.zip、aws-sdk-net35.zip があるけど試していません)

スクリーンショット20211118_001.png

A DLLは複数あるけど、.NET Standard 2.0版 を使用する(たぶん)


.NET Standard 2.0を選んだのは、
Unity > Project Settings > Player > Configuration(Android) > API Compatibility Level = .NET 4.x
としているので、下位互換性のあるStandard 2.0を選んだ方が無難だと思ったから。

スクリーンショット20211118_002.png

あと、DLLを直接ダウンロードする方法も紹介されていました↓

Unity のサポートに関する特別な考慮事項:
https://docs.aws.amazon.com/ja_jp/sdk-for-net/v3/developer-guide/unity-special.html

先ほどのZipファイルを解凍すると、AWSのSDKがすべて入っているので、必要なDLLだけをUnityプロジェクトにコピーして使用します。

■使用するサービス
・Cognito (ユーザー認証)
・DynamoDB (サーバーレス key-value NoSQL)

■必要なDLL
使いたいサービスに直結するDLL
・AWSSDK.CognitoIdentity.dll
・AWSSDK.CognitoSync.dll
・AWSSDK.DynamoDBv2.dll
上記3点を使用する際に必要とされるDLL
・AWSSDK.Core.dll
・AWSSDK.SecurityToken.dll
・Microsoft.Bcl.AsyncInterfaces.dll
・System.Runtime.CompilerServices.Unsafe.dll
・System.Threading.Tasks.Extensions.dll

なぜ2サービスだけなのにDLLがこんなに必要かというと、依存関係があるから。

例を挙げると、AWSSDK.CognitoIdentityを使用したい場合、AWSSDK.CoreとAWSSDK.SecurityTokenが必要になります。
https://www.nuget.org/packages/AWSSDK.CognitoIdentity/
より、
スクリーンショット20211118_003.png

こんな感じで、必要とされるDLLを調べます。

NuGetで依存関係を確認する方法↓
例)AWSSDK.Coreの場合:
https://www.nuget.org/packages/AWSSDK.Core/

各DLLの依存関係一覧:
https://github.com/aws/aws-sdk-net/blob/master/generator/ServiceModels/_sdk-versions.json

後で気づいたけど、どのDLLも@でダウンロードしたZipファイルに格納されていました。
後述で、NuGetから直接ダウンロードしていますが、その作業は不要でした。
でも勉強のため、残しておきます。

B SDKの圧縮ファイル(.nupkg)は、MacではWクリックでは解凍できない


上記で挙げたNuGetページの右側に「Download package」というリンクがあります。そこからDLLを直接ダウンロードすることができますが、圧縮されて「.nupkg」という拡張子になっていています。
調べてみると、この拡張子を「.zip」に書き換えて解凍できるとありましたが、Macを使っている自分の場合は解凍できませんでした。

解凍できた方法は2つ。
@ 「.nupkg」はそのままで、右クリック > このアプリケーションで開く > アーカイブユーティリティ.app
スクリーンショット20211118_004.png

A 上記の方法を試したら「.nupkg」と「.cpgz」に交互に変わるだけで解凍されない場合は、ターミナルから「unzip」コマンドを使って解凍

Macでzipファイルを解凍するとcpgzファイルが生成されてしまう時の対処法:
https://3daysam.com/post-301/

C メソッド定義が重複するので、新旧のDLLは共存させない


これでDLLが揃ったので、Unityプロジェクトに適当なディレクトリを作ってそこに入れます。
ただし、既に入っている古い方のDLLと競合するので、古い方はUnityプロジェクトから外しておきます(念のため、削除せずに残しておきます)

D メソッドが非同期用になっていたので、Taskで対応


dynamoDBから1項目を取得するコマンドに「GetItem」がありますが、SDKを最新版にしたところ、そのメソッドがなくなり、「GetItemAsync」になっていました。
スクリーンショット20211118_005.png

これにより、GetItemは非同期処理になったようで、Taskを使う必要が出てきました。
これまでUnityでTaskを使ったことがなかったので勉強しました↓

【Unity】【C#】Unityでasync/await、Task入門!非同期処理をスマートに書く:
https://light11.hatenadiary.com/entry/2019/03/05/221311

DBクライアントの取得などは割愛して、項目を取得する部分だけを抜粋するとこんな感じ。

public void Hogehoge()
{
// 戻り値は使わないけど、こう書くのが習わしらしい
var doc = GetData();
// こちら側でdocからデータを得ようとするとフリーズするので注意。非同期メソッドの中でデータを取得すること。
}

async Task<Document> GetData()
{
Table table = Table.LoadTable(_ddbClient, "[テーブル名]");
var doc = await table.GetItemAsync("[該当するキー]");
Debug.Log(doc["q"]);         // <----- 目的の項目のデータが取れた!!
return doc;
}

// テーブル定義
[DynamoDBTable("[テーブル名]")]
public class MyTable
{
[DynamoDBHashKey] // ハッシュキー
public string key { get; set; }
[DynamoDBProperty] // 属性
public string q { get; set; }
}



SDKが新しくなって、プログラムで修正が必要になった箇所は上記のようなテーブルにアクセスする箇所だけだった。
Cognitoを使って認証するところや、DBに接続する準備の処理はこれまで通りだった。

色々調べたけど、同期のままのメソッド例が多く、サンプル通り動かないものもあり、非同期のメソッドを使ってデータを取得する方法を見つけるまでに苦労しました。
今回のが良い方法かはわかりませんが、誰かの助けになれば幸いです。

posted by be-style at 23:17| Comment(0) | Unity