roblox-input について
Roblox 開発者向けに、入力処理とカメラを解説するスキルです。デバイスをまたぐ操作の構築を対象に、推奨の Input Action System と低レベル・旧式の方法、カメラ実装、クロスプラットフォームの確認事項を扱います。
主な機能
- 01デバイス横断の Input Action System
- 02生入力と旧式のバインド
- 03入力コンテキストとアクション状態
- 04デバイスに応じた操作プロンプト
- 05カスタムカメラの更新方法
- 06クロスプラットフォームのテスト項目
活用シーン
- 01キーボード、ゲームパッド、タッチ操作の構築
- 02メニューや乗り物に応じた操作方式の切り替え
- 03利用中のデバイスに合わせた操作表示
- 04カスタムカメラや画面からワールドへのレイ実装
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ el4cteo/ roblox-skills --skill roblox-inputインストール後、Claude Code で/roblox-inputを入力して読み込まれたか確認します。
詳細
Roblox の入力とカメラ
アプローチの選択
| アプローチ | 使用する場面 |
|---|---|
Input Action System (InputContext → InputAction → InputBinding) | 新しいゲームプレイの操作。インスタンスとして設定するクロスデバイスバインディング、有効化/無効化するコンテキスト、組み込みのオンスクリーンボタンバインディング、プロンプト表示。推奨。 |
UserInputService のイベント | 生の入力、テキストを伴わないホットキー、マウス位置/デルタ、タッチジェスチャー、デバイス検出。 |
ContextActionService:BindAction | レガシー/シンプルなモバイルボタン付きバインド。既存のコード。 |
すべての入力処理はクライアント側です。リモート経由でインテントをサーバーに送信し、サーバーが検証します。
Input Action System
構造(通常は ReplicatedStorage.Inputs 内、またはクライアントスクリプトから作成):
Inputs (Folder)
PlayContext (InputContext, Priority 1000) -- gameplay controls
Sprint (InputAction, Type = Bool)
Keyboard (InputBinding, KeyCode = LeftShift)
Gamepad (InputBinding, KeyCode = ButtonL3)
Touch (InputBinding, UIButton = <on-screen TextButton>)
MenuContext (InputContext, Priority 2000, Sink = true, Enabled = false)
InputAction.Type:Bool(押す/離す)、Direction1D(トリガー、ズーム)、Direction2D(移動、カメラ)、Direction3D(飛行)、ViewportPosition(ポインター位置)。- イベント:
Pressed、Released(Boolのみ)、すべての型に対するStateChanged(value)。action:GetState()は現在の値を読み取ります。 InputBindingのフィールド:KeyCode、複合方向Up/Down/Left/Right/Forward/Backward、Scale(例:MouseDelta/TouchDeltaには0.01)、アナログトリガー用のPressedThreshold/ReleasedThreshold、 コード(複合キー)用のPrimaryModifier/SecondaryModifier(Ctrl+S)、GUI ボタンからアクションを駆動するUIButton、 プロンプト用のDisplayName/DisplayImage。InputContext.Enabledはコントロールスキーム全体を切り替えます(ゲームプレイ ↔ メニュー ↔ 乗り物)。Priority+Sinkにより、上位のコンテキストがキーを消費し、下位のコンテキストも同時に発火しないようにできます。Workspace.PlayerScriptsUseInputActionSystem = Enabledを設定すると、Roblox のデフォルトのプレイヤー/カメラ スクリプトもこのシステムを使用します(サーバー権限のために必須)。
--!strict
-- Client: build a Sprint action in code and react to it.
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local context = Instance.new("InputContext")
context.Name = "PlayContext"
context.Priority = 1000
local sprint = Instance.new("InputAction")
sprint.Name = "Sprint"
sprint.Type = Enum.InputActionType.Bool
sprint.Parent = context
local keyboard = Instance.new("InputBinding")
keyboard.KeyCode = Enum.KeyCode.LeftShift
keyboard.Parent = sprint
local gamepad = Instance.new("InputBinding")
gamepad.KeyCode = Enum.KeyCode.ButtonL3
gamepad.Parent = sprint
context.Parent = player:WaitForChild("PlayerScripts")
local function setSprinting(on: boolean)
local character = player.Character
local humanoid = character and character:FindFirstChildOfClass("Humanoid")
if humanoid then
humanoid.WalkSpeed = if on then 24 else 16 -- server should validate/own real speed limits
end
end
sprint.Pressed:Connect(function()
setSprinting(true)
end)
sprint.Released:Connect(function()
setSprinting(false)
end)
適切なキー/ボタンを表示: InputActionLabel(ベータ)は現在のデバイス用のバインディングを自動レンダリングします。
または action.PreferredBinding(+ その DisplayName/KeyCode)と UserInputService:GetStringForKeyCode
/ GetImageForKeyCode を読み取り、GetPropertyChangedSignal("PreferredBinding") で更新します。
UserInputService の要点
--!strict
local UserInputService = game:GetService("UserInputService")
UserInputService.InputBegan:Connect(function(input: InputObject, gameProcessedEvent: boolean)
if gameProcessedEvent then
return -- typing in a TextBox, clicking UI, or a core-script action consumed it
end
if input.KeyCode == Enum.KeyCode.E then
print("interact")
elseif input.UserInputType == Enum.UserInputType.MouseButton1 then
print("click at", input.Position)
end
end)
local function onPreferredInputChanged()
local preferred = UserInputService.PreferredInput -- KeyboardAndMouse | Touch | Gamepad
print("show prompts for", preferred)
end
UserInputService:GetPropertyChangedSignal("PreferredInput"):Connect(onPreferredInputChanged)
onPreferredInputChanged()
- 必ず
gameProcessedEventを尊重してください。そうしないと、プレイヤーがチャットで入力中にアビリティを発動してしまいます。 PreferredInputはプレイヤーが実際に使用しているものを反映します(スマートフォン + Bluetooth ゲームパッド →Gamepad)。TouchEnabled/KeyboardEnabledだけで分岐しないでください。- マウス: FPS では
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter(他のスクリプトがリセットする可能性がある場合は、 一人称中は毎フレーム設定)、GetMouseLocation()(トップバーのインセットを含む)、MouseDeltaSensitivity、MouseIconEnabled。 - ゲームパッド:
GetConnectedGamepads、GamepadConnected/Disconnected、InputChangedでのサムスティックのinput.Position(デッドゾーン ≈ 0.15 を適用)。ハプティクス:HapticService/HapticEffect。 - タッチ:
TouchTap、TouchLongPress、TouchPinch、TouchSwipe。デフォルトのコントロールは、置き換える場合にのみ非表示にしてください (GuiService.TouchControlsEnabled)。 - 上書きできない予約キー: Esc/Start(メニュー)、F9(コンソール)、F11、F12、PrintScreen。チャットの
/、 Tab(プレイヤーリスト)、バックパックとツール番号キーは、それらのコア機能を無効化しない限り使用されます。
ContextActionService(レガシー互換)
ContextActionService:BindAction(name, handler, createTouchButton, ...inputs)。ハンドラーは
(actionName, inputState, inputObject) -> Enum.ContextActionResult?。他の
バインディングに入力を認識させるには Pass を返します。順序付けには BindActionAtPriority を、コンテキストが
終了したとき(例: ツールの装備解除)には UnbindAction を使用します。新しい作業には Input Action System を推奨します。
カスタムカメラ
--!strict
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local camera = workspace.CurrentCamera
local OFFSET = Vector3.new(0, 30, 20)
camera.CameraType = Enum.CameraType.Scriptable
RunService:BindToRenderStep("TopDownCamera", Enum.RenderPriority.Camera.Value + 1, function()
local character = Players.LocalPlayer.Character
local root = character and character:FindFirstChild("HumanoidRootPart") :: BasePart?
if root then
local target = root.Position
camera.CFrame = CFrame.lookAt(target + OFFSET, target)
end
end)
-- Restore: RunService:UnbindFromRenderStep("TopDownCamera"); camera.CameraType = Enum.CameraType.Custom
- カメラの更新には
Heartbeatやtask.waitのループではなく、BindToRenderStep(レンダリング前に実行され、順序が設定されます)を使用します。 camera.CFrame:Lerp(goal, 1 - math.exp(-speed * deltaTime))で滑らかにします(フレームレートに依存しません)。- 一人称視点:
player.CameraMode = Enum.CameraMode.LockFirstPersonに設定します。ズーム範囲はplayer.CameraMinZoomDistance/CameraMaxZoomDistanceで設定します。揺れを加える場合は、パーツを動かさずに CFrame にオフセットを加えます。 - 画面座標からワールド座標への変換:
camera:ViewportPointToRay(x, y)/ScreenPointToRayとworkspace:Raycastを使用します。
クロスプラットフォーム対応チェックリスト
- すべてのアクションに、キーボード、ゲームパッド、およびタッチの操作を割り当てます(タッチ操作には
UIButtonまたは画面上のボタンを使用します)。 PreferredInputの変更に応じて、プロンプトやヒントを更新します。コンソールの UI は十字キーで操作でき、B ボタンで閉じられるようにします。- ホバー時のみの操作は避けます(タッチにはホバー操作がありません)。破壊的な操作には、長押しによる確認を設けます。
- Studio の Device Simulator(タッチ用ヒントを含む)と Controller Emulator でテストします。
関連スキル
roblox-ui(ボタン、ゲームパッドでの選択)、roblox-characters-animation(移動、アビリティ)、
roblox-networking(操作意図の送信)、roblox-physics(乗り物)。