【VRChat】AWSを使ったアクセスカウンター制作手順
概要
AWSのLambdaとDynamoDBを利用したVRChatのワールドのアクセスカウンターを作る手順を覚書レベルで記します。
初めて作ったVRChatのワールドとサーバーを連携させるギミックなので間違いもあると思います。予めご容赦ください。
自分が初めてAWSを使った際に、どこに何があるかわからないことが多かったので、AWSのスクリーンショットが多めです。
環境
-
AWS Lambda: Python 3.13
-
Unity 2022.3.22f1
-
VRChat SDK - Base 3.6.1
-
VRChat SDK - Worlds 3.6.1
手順
AWSのリージョン設定
東京に設定する
アクセス数を保存するデータベースの作成(DynamoDB)
DynamoDBを選択
テーブルを作成
テーブル名(Table1)とパーティションキー(PartitionKey)を設定
項目を作成
PartitionKeyをPlayerCountとし、アクセス数を保存する数値タイプのCountValueというデータを登録する。
アクセス数をカウントアップする関数の作成(Lambda)
Lambdaを選択
関数を作成
関数名をCountUpとし、ランタイムでPythonを指定する
関数URLを有効化にチェックを入れ、認証タイプでNONEを指定し、関数を作成
タイムアウト時間を3秒から10秒に変更しておく
Lambda関数のコードを貼り付けてDeploy(保存)する
import json
import boto3
def lambda_handler(event, context):
""" VRChat以外からの通信だったら弾く処理 (user-agentは偽装可能なので気持ち程度)
try:
UserAgent = event["headers"]["user-agent"]
except:
return "Error"
if False == ("UnityPlayer" in UserAgent):
return "Error"
"""
dynamodb = boto3.resource("dynamodb")
table = dynamodb.Table("Table1")
# CountValueの値をカウントアップ
table.update_item(
Key = {"PartitionKey" : "PlayerCount"}, # PartitionKey選択
UpdateExpression = "SET #Para = #Para + :Value", # 更新式 (i = i + 1と同じことを書いてある)
ExpressionAttributeNames = {"#Para" : "CountValue"}, # 更新式の変数名
ExpressionAttributeValues = {":Value" : 1} # 更新式の値
)
# CountValueの値を返す
DataDict = table.get_item(Key={"PartitionKey" : "PlayerCount"}).get("Item")
return DataDict["CountValue"]
LambdaからDynamoDBへのアクセス権限設定
IAMを選択
Lambda関数の名前(CountUp)がついているロールをクリック
インラインポリシーを作成をクリック
サービスの選択でDynamoDBを選択
Lambda関数のコード内で使用しているメソッドのGetItemとUpdateItemにチェックを入れる
別タブでDynamoDBを開き、Table1のARNをコピーする
IAMに戻り、リソースARN欄に貼り付けてARNを追加し、次へをクリック
好きなポリシー名をつけてポリシーを作成する (PlayerCountPolicyとした)
Lambda関数を実行するUdonSharpの作成
Lambda関数の関数URLをコピーしておく
Lambda関数の関数URLを以下のUdonSharpのVRCUrlにコピペする
using UdonSharp;
using UnityEngine;
using UnityEngine.UI;
using VRC.SDKBase;
using VRC.Udon;
using VRC.SDK3.StringLoading;
using VRC.Udon.Common.Interfaces;
public class AccessCounter : UdonSharpBehaviour
{
[SerializeField] private Text TextObj;
private VRCUrl URL = new VRCUrl("Lambda関数の関数URLをここにコピペ");
void Start()
{
VRCStringDownloader.LoadUrl(URL, (IUdonEventReceiver)this);
TextObj.text = "Loading...";
}
// 成功
public override void OnStringLoadSuccess(IVRCStringDownload Result)
{
TextObj.text = Result.Result;
}
// 失敗
public override void OnStringLoadError(IVRCStringDownload Result)
{
TextObj.text = "Error";
}
}
実行結果
UdonSharpスクリプトを適当なオブジェクトにアタッチし、InspectorでTextオブジェクトを設定してください
アップロードしたワールドにJoin後、1回Rejoinしてアクセス数が2に増えた
おまけ (Lambdaに引数を渡す)
アクセスカウンターが作れたら、次はUdonSharpからLambdaに引数を渡して、その引数に応じてサーバー側で様々な処理をさせたくなると思います。
そういった場合は、URLクエリパラメータ(クエリストリング)というものを使ってLambdaに好きな情報を渡すことができます。
クエリパラメータはURL末尾の?以降に記述することができます。例えばa=0、b=1、c=ABCという情報を渡したい場合、以下のようなURLになります。
https://~.on.aws/?a=0&b=1&c=ABC
このURLを以下のようなクエリパラメータを返すだけのLambda関数に送ってみます
import json
import boto3
def lambda_handler(event, context):
return event["queryStringParameters"]
すると以下のようなjsonデータが返ってきます。
{"a":"0","b":"1","c":"ABC"}
このような感じで、クエリパラメータを使ってLambdaに好きな情報を渡すことができます。
ただし、UdonSharpではVRCUrlの内容をユーザーからの入力無しに動的に変更できないため、例えばa=0,a=1,a=2,...a=9の10種類のクエリパラメータをLambda関数に渡したい場合、以下のようにあらかじめ10種類のVRCUrlを用意しておく必要があります。
private VRCUrl[] UrlArray = {
new VRCUrl("https://~.on.aws/?a=0"),
new VRCUrl("https://~.on.aws/?a=1"),
new VRCUrl("https://~.on.aws/?a=2"),
new VRCUrl("https://~.on.aws/?a=3"),
new VRCUrl("https://~.on.aws/?a=4"),
new VRCUrl("https://~.on.aws/?a=5"),
new VRCUrl("https://~.on.aws/?a=6"),
new VRCUrl("https://~.on.aws/?a=7"),
new VRCUrl("https://~.on.aws/?a=8"),
new VRCUrl("https://~.on.aws/?a=9")};
例として、2025年2月にVRChatユーザーのPCスペックを集計するワールドを作ったのですが、このワールドでは、CPU、GPU、RAM、OSをPCVRとDesktop別に集計するためにクエリパラメータ別に1198個のVRCUrlを使っています。
Discussion