mcpField
R
roblox-input

roblox-input

github.com/el4cteo开发61577 次安装2 周前更新
代码仓库

关于 roblox-input

面向 Roblox 开发者的输入处理与摄像机技能,适用于构建跨设备游戏控制。内容讲解推荐的 Input Action System,也介绍底层及旧式方案、摄像机实现和跨平台检查。

主要功能

  1. 01跨设备 Input Action System
  2. 02原始输入与旧式绑定
  3. 03输入上下文与动作状态
  4. 04适配设备的操作提示
  5. 05自定义摄像机更新模式
  6. 06跨平台测试清单

适用场景

  1. 01构建键盘、手柄和触屏控制
  2. 02为菜单或载具切换控制方案
  3. 03显示当前设备对应的操作提示
  4. 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旧式/简单的带移动按钮绑定;已有代码。

所有输入处理都在客户端进行。通过 remote 向服务发送意图;由服务进行验证。

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(beta)会自动渲染当前设备的绑定, 或者读取 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 反映玩家实际使用的输入方式(手机 + 蓝牙手柄 → 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),其中 handler 为 (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
  • 在 BindToRenderStep 中更新摄像机(在渲染前运行,按顺序执行),不要使用 Heartbeat/task.wait 循环。
  • 使用 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(载具)。

评论

支持 Markdown