mcpField
R
roblox-studio-emulation

roblox-studio-emulation

github.com/flatbedjテスト・品質049 回インストール6 週間前に更新
リポジトリ

roblox-studio-emulation について

roblox-studio-emulationは、Roblox Studioでモバイル、マルチプレイヤー、境界条件を検証するためのテストスキルです。Studioのメニュー操作、リモートイベントを使ったテスト、検証結果の限界の報告方法を説明します。

主な機能

  1. 01タッチやデバイス条件のエミュレーション
  2. 02AppleScriptによるStudioのTestメニュー操作
  3. 03実際のリモートを使ったマルチプレイヤーのテスト
  4. 04クライアント属性によるシナリオ設定
  5. 05実動作・ロジック・未検証の区別

活用シーン

  1. 01タッチ専用UIの動作確認
  2. 022人目のクライアントなしでパーティー状態を確認
  3. 03合成入力で分岐をテスト

MCP 対応

このスキルはRoblox Studio MCPツールと併用します。エミュレーター切り替え後の再接続には、`list_roblox_studios`、`set_active_studio`、`start_stop_play`を参照しています。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/flatbedj/roblox-skills --skill roblox-studio-emulation

インストール後、Claude Code で/roblox-studio-emulationを入力して読み込まれたか確認します。

詳細

ソロプレイテストでは再現できない状況をエミュレートする

MCP ツールだけではテストが不可能に見える種類のテストが 2 つあり、ユーザーに任せたくなるかもしれません。どちらも自分で実施できます。何かのテストにユーザーが必要だと言う前に、ここを確認してください。

通常の開発ループについては roblox-studio-workflow を、MCP ツールボックスについては roblox-studio-mcp を参照してください。


1. デバイスエミュレーション(モバイル/タブレット/タッチ)— Studio のメニューバーから

Studio は macOS のアクセシビリティ機能にウィンドウを公開していないため(count windows → 0)、サイズを変更できません。 しかし、メニューバー全体は公開しているため、Test メニューを操作できます。

# one-time: the user must grant Terminal (or your host app) Accessibility permission
#   System Settings → Privacy & Security → Accessibility
# symptom if missing: "osascript is not allowed assistive access. (-1719)"

osascript -e 'tell application "Roblox Studio" to activate'
osascript -e 'tell application "System Events" to tell process "RobloxStudio" \
  to click menu item "Device Emulator" of menu 1 of menu bar item "Test" of menu bar 1'

プロセス名は RobloxStudio です(「Roblox Studio」でも「RobloxStudioBeta」でもありません)。

実際に反映されたかどうかを確認してください。決めつけずに、Play を開始して実際の値を読み取ります。

local cam = workspace.CurrentCamera
local UIS = game:GetService("UserInputService")
-- desktop: ~1920x1080, TouchEnabled=false
-- emulated: device-sized viewport, TouchEnabled=TRUE
return cam.ViewportSize, UIS.TouchEnabled

TouchEnabled = true は、タッチ専用のコードパス(サムスティックの配置スペース、タッチレイアウトの分岐、POS_SHOWN オフセット)が有効になったことを示します。

Test メニュー全体(便利な項目):

項目備考
Device Emulatorエミュレーションの切り替え
Controller Emulator / Player Emulatorゲームパッド/プレイヤー状態のエミュレーション
Start Test SessionAdd Clients の前に必要
Add ClientsPlay Solo では無効。Test Session 内では有効
Toggle Client View、Pause Client、End Sessionマルチクライアントセッションの操作

クリックする前に項目を列挙し、有効状態を確認します。

osascript -e 'tell application "System Events" to tell process "RobloxStudio" \
  to get name of every menu item of menu 1 of menu bar item "Test" of menu bar 1'
osascript -e 'tell application "System Events" to tell process "RobloxStudio" \
  to get enabled of menu item "Add Clients" of menu 1 of menu bar item "Test" of menu bar 1'
制限事項
  • 特定のデバイス(iPhone と iPad など)を選ぶ操作には、ウィンドウ内のドロップダウンを使用しますが、これは AX では公開されていません。現在選択されているデバイスが使われます。特定の幅が必要な場合は、一度ユーザーに設定を依頼してください。レイアウトが実際に崩れるのは、幅の狭いスマートフォンです。
  • エミュレーターを切り替えると、現在の Play セッションが終了し、MCP 接続が切れることがあります。list_roblox_studios → set_active_studio で再接続してから、start_stop_play を実行してください。
  • 終了したらエミュレーターを OFF に戻してください。そうしないと、その後のスクリーンショットがすべてタッチデバイスのものになります。

2. 2 つ目のクライアントを使わずにマルチプレイヤー機能をテストする — 実際のリモートを呼び出す

通常、マルチクライアントセッションを起動するよりも速く、正確です。 Server VM と Client VM は DataModel を共有しているため、Server VM からの FireClient は実際のクライアントモジュールに届き、その後の処理(シグナルハンドラー、キャッシュ状態、UI の更新)を実行します。

-- datamodel_type = "Server"
local Remotes = require(game:GetService("ReplicatedStorage"):WaitForChild("Shared").Remotes)
local plr = game.Players:GetPlayers()[1]

-- pretend the server told us we joined someone's party
Remotes.event("PartyUpdated"):FireClient(plr, {
    ownerUserId = 99999999, ownerName = "TestHost",
    members = { { userId = plr.UserId, name = plr.DisplayName } },
})

次に、Client VM から観測可能なインスタンス状態を検証します(モジュール内部は使わないでください。別の VM であり、require は複製されたモジュールを返します)。

-- datamodel_type = "Client"
local on = 0
for _, p in game:GetService("CollectionService"):GetTagged("Plot") do
    for _, d in p:GetDescendants() do
        if d:IsA("ProximityPrompt") and d.Name == "PartyPrompt" and d.Enabled then on += 1 end
    end
end
return on

必ず往復をテストしてください。「参加」状態を発火して検証し、次に「退出」状態を発火して(FireClient(plr, nil))、元に戻ることを検証します。一方向のテストでは、状態が戻らなくなる問題が隠れてしまいます。これはより深刻なバグです(プロンプトが非表示のままになると、そのプレイヤーにとって機能が使えなくなります)。

前提条件を偽装する

クライアント側の属性書き込みだけでシナリオを設定できます。クライアントコードは同じ属性を読み取り、GetAttributeChangedSignal はローカルで発火するためです。

-- datamodel_type = "Client" — pretend another player owns this plot
workspace.Map.Plots.Plot1:SetAttribute("OwnerUserId", 99999999)
-- ... run the test ...
workspace.Map.Plots.Plot1:SetAttribute("OwnerUserId", nil)  -- ALWAYS clean up
これが機能しない場合

偽装したユーザーが**実際にオンラインの Player**であることを必要とするコードは、この方法では偽装できません。例:Players:GetPlayerByUserId(owner) を実行し、このチェックに失敗したものを削除するポーリングループは、設定を直ちに取り消します。症状として、作成したものが 1 秒以内に消えます。

次のいずれかに切り替えてください。

  • Test ▸ Start Test Session ▸ Add Clients を使って、本物の 2 人目のプレイヤーを追加する、または
  • Client VM で合成入力を使って純粋なロジックをユニットテストする。出荷時のガード/分岐をそのまま再現し、テーブルテストを行います。
local cases = {
    { "nil payload",     nil,                 true  },
    { "empty string",    "",                  true  },
    { "garbage base64",  "!!!not-base64!!!",  true  },
    { "short buffer",    Base64.encode(short),true  },
    { "valid buffer",    Base64.encode(full), false },
}
-- assert blocked == expected for each; report N/N

これは実際に報告できる結果です。ただし、検証したのはロジックであり、描画を含む完全な経路ではないことを明示してください。


正確な報告

毎回、次の 3 つを区別してください。

  • 実環境で検証済み — 操作を実行し、その効果を確認した。
  • ロジックを検証済み — 合成入力で分岐をテーブルテストした。完全な経路は未テスト。
  • 未テスト — その旨を伝え、何が必要かを正確に説明する。

「コンパイルできて見た目も正しい」を、検証済みとして報告してはいけません。

コメント