UserInputService

显示已弃用

*此内容使用人工智能(Beta)翻译,可能包含错误。若要查看英文页面,请点按 此处

无法创建
服务
未复制

UserInputService 是用于检测和捕获用户设备上可用的不同类型输入的服务。

该服务的主要目的是允许体验与多种可用输入形式合作,例如游戏手柄、触摸屏和键盘。它允许 LocalScript 根据设备执行不同的操作,从而为最终用户提供最佳体验。

这服务的一些用途包括在用户与 GUI、工具和其他游戏实例互动时检测用户输入。为了检测用户输入,服务必须查找服务事件。例如,服务可以检测事件,例如当用户使用 UserInputService.TouchStarted 触摸移动设备屏幕,或使用 UserInputService.GamepadConnected 连接游戏手柄,例如 Xbox 控制器到他们的设备。

由于此服务仅限客户端使用,它只能在 LocalScriptModuleScriptLocalScript 要求时才能工作。由于 UserInputService 只是客户端,游戏中的用户只能检测自己的输入 - 而不是他人的输入。

还见 ContextActionService , 一种服务,可以让你将函数绑定到多个用户输入。

代码示例

The following example demonstrates one of many usage examples of handling a UserInputService event.

UserInputService

-- We must get the UserInputService before we can use it
local UserInputService = game:GetService("UserInputService")
-- A sample function providing one usage of InputBegan
local function onInputBegan(input, _gameProcessed)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
print("The left mouse button has been pressed!")
end
end
UserInputService.InputBegan:Connect(onInputBegan)

概要

属性

方法

活动

属性

AccelerometerEnabled

只读
未复制
读取并联

该属性描述用户的设备是否具有加速器

加速器是一种在大多数移动设备中找到的组件,用于测量加速(速度变化)。

例如,以下代码片段显示了如何检查用户的设备是否具有加速器。


local UserInputService = game:GetService("UserInputService")
local accelerometerEnabled = UserInputService.AccelerometerEnabled
if accelerometerEnabled then
print("Accelerometer enabled!")
else
print("Accelerometer not enabled!")
end

如果设备启用了加速器,你可以使用 UserInputService:GetDeviceAcceleration() 函数或跟踪当设备的加速度发生变化时使用 UserInputService.DeviceAccelerationChanged 事件来获取当前加速度。

由于 UserInputService 仅为客户端,此属性只能在 LocalScript 中使用。

代码示例

This code adds a force on a part so that it falls in the direction of actual gravity relative to the user's device.

In order for this example to work as expected, it must be placed in a LocalScript and the user's device must have an accelerometer.

Move a Ball using the Accelerometer

local Workspace = game:GetService("Workspace")
local UserInputService = game:GetService("UserInputService")
local ball = script.Parent:WaitForChild("Ball")
local mass = ball:GetMass()
local gravityForce = ball:WaitForChild("GravityForce")
local function moveBall(gravity)
gravityForce.Force = gravity.Position * Workspace.Gravity * mass
end
if UserInputService.AccelerometerEnabled then
UserInputService.DeviceGravityChanged:Connect(moveBall)
end

This example controls the player's Camera so that it matches the player's device orientation via using the device's gyroscope and accelerometer.

The camera is positioned inside the player's head, and updated to move with the player and the user's device rotation, by executing the following line every RenderStep:


camera.CFrame = CFrame.new(head.Position - Vector3.new(0,8,10)) *
currentRotation

The code sample relies on the device's gyroscope to determine when the player rotates their device. It does so by connecting to the DeviceRotationChanged() event.

The code sample relies on the device's accelerometer to retrieve the gravity vector used to determine the device's orientation (whether it is flipped upside down or not). To determine whether the device's orientation is upside down, the code sample uses the DeviceGravityChanged() event.

Since the script places the camera inside the head to create a first-person camera, the limbs are made transparent by the HideCharacter() function so that the player does not see their Player.Character when rotating the camera.

In order for this example to work as expected, it must be placed in a LocalScript and the user's device must have a gyroscope and an accelerometer.

Create a Gyroscopic Camera

local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local character = player.CharacterAdded:Wait()
local head = character:WaitForChild("Head")
local camera = workspace.CurrentCamera
local currentRotation = camera.CFrame -- CFrame.new(Vector3.new(0,0,0), Vector3.new(0,0,0))
local lastInputFrame = nil
local upsideDown = false
task.wait()
local orientationSet = false
local function GravityChanged(gravity)
if not orientationSet then
upsideDown = (gravity.Position.X < -0.5 or gravity.Position.Z > 0.5)
orientationSet = true
end
end
local function RotationChanged(_rotation, rotCFrame)
if orientationSet then
if not lastInputFrame then
lastInputFrame = rotCFrame
end
local delta = rotCFrame * lastInputFrame:inverse()
local x, y, z = delta:ToEulerAnglesXYZ()
if upsideDown then
delta = CFrame.Angles(-x, y, z)
else
delta = CFrame.Angles(x, -y, z)
end
currentRotation = currentRotation * delta
lastInputFrame = rotCFrame
end
end
local function HideCharacter()
for _, limb in pairs(character:GetChildren()) do
if limb:IsA("Part") then
limb.Transparency = 1
end
end
end
if UserInputService.GyroscopeEnabled then
UserInputService.DeviceGravityChanged:Connect(GravityChanged)
UserInputService.DeviceRotationChanged:Connect(RotationChanged)
HideCharacter()
RunService:BindToRenderStep("Camera", Enum.RenderPriority.Camera.Value, function()
camera.CFrame = CFrame.new(head.Position - Vector3.new(0, 8, 10)) * currentRotation
camera.Focus = CFrame.new(currentRotation * Vector3.new(0, 0, -10))
end)
end

GamepadEnabled

只读
未复制
读取并联

该属性描述用户使用的设备是否有可用的游戏手柄。如果游戏手柄可用,你可以使用 UserInputService:GetConnectedGamepads() 来检索连接的游戏手柄列表。

由于 UserInputService 仅为客户端,此属性只能在 LocalScript 中使用。

还见:

代码示例

If you are using the default controls, you do not need to worry about this. If you're creating a custom script for handling gamepad controls, this is a good template for retrieving which gamepad enum you should use as the primary gamepad controller.

How to Set the Active Gamepad for Input

local UserInputService = game:GetService("UserInputService")
local function getActiveGamepad()
local activeGamepad = nil
local connectedGamepads = UserInputService:GetConnectedGamepads()
if #connectedGamepads > 0 then
for _, gamepad in connectedGamepads do
if activeGamepad == nil or gamepad.Value < activeGamepad.Value then
activeGamepad = gamepad
end
end
end
if activeGamepad == nil then -- Nothing is connected; set up for "Gamepad1"
activeGamepad = Enum.UserInputType.Gamepad1
end
return activeGamepad
end
if UserInputService.GamepadEnabled then
local activeGamepad = getActiveGamepad()
print(activeGamepad)
end

GyroscopeEnabled

只读
未复制
读取并联

该属性描述用户的设备是否具有陀螺仪。

陀螺仪是一种在大多数移动设备中找到的组件,可检测方向和旋转速度。

如果用户的设备具有陀螺仪,您可以使用 UserInputService:GetDeviceRotation() 函数和 UserInputService.DeviceRotationChanged 事件将其融入到游戏中。


local UserInputService = game:GetService("UserInputService")
local gyroIsEnabled = UserInputService.GyroscopeEnabled
if gyroIsEnabled then
print("Gyroscope is enabled!")
else
print("Gyroscope is not enabled!")
end

由于 UserInputService 仅为客户端,此属性只能在 LocalScript 中使用。

代码示例

This example controls the player's Camera so that it matches the player's device orientation via using the device's gyroscope and accelerometer.

The camera is positioned inside the player's head, and updated to move with the player and the user's device rotation, by executing the following line every RenderStep:


camera.CFrame = CFrame.new(head.Position - Vector3.new(0,8,10)) *
currentRotation

The code sample relies on the device's gyroscope to determine when the player rotates their device. It does so by connecting to the DeviceRotationChanged() event.

The code sample relies on the device's accelerometer to retrieve the gravity vector used to determine the device's orientation (whether it is flipped upside down or not). To determine whether the device's orientation is upside down, the code sample uses the DeviceGravityChanged() event.

Since the script places the camera inside the head to create a first-person camera, the limbs are made transparent by the HideCharacter() function so that the player does not see their Player.Character when rotating the camera.

In order for this example to work as expected, it must be placed in a LocalScript and the user's device must have a gyroscope and an accelerometer.

Create a Gyroscopic Camera

local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local character = player.CharacterAdded:Wait()
local head = character:WaitForChild("Head")
local camera = workspace.CurrentCamera
local currentRotation = camera.CFrame -- CFrame.new(Vector3.new(0,0,0), Vector3.new(0,0,0))
local lastInputFrame = nil
local upsideDown = false
task.wait()
local orientationSet = false
local function GravityChanged(gravity)
if not orientationSet then
upsideDown = (gravity.Position.X < -0.5 or gravity.Position.Z > 0.5)
orientationSet = true
end
end
local function RotationChanged(_rotation, rotCFrame)
if orientationSet then
if not lastInputFrame then
lastInputFrame = rotCFrame
end
local delta = rotCFrame * lastInputFrame:inverse()
local x, y, z = delta:ToEulerAnglesXYZ()
if upsideDown then
delta = CFrame.Angles(-x, y, z)
else
delta = CFrame.Angles(x, -y, z)
end
currentRotation = currentRotation * delta
lastInputFrame = rotCFrame
end
end
local function HideCharacter()
for _, limb in pairs(character:GetChildren()) do
if limb:IsA("Part") then
limb.Transparency = 1
end
end
end
if UserInputService.GyroscopeEnabled then
UserInputService.DeviceGravityChanged:Connect(GravityChanged)
UserInputService.DeviceRotationChanged:Connect(RotationChanged)
HideCharacter()
RunService:BindToRenderStep("Camera", Enum.RenderPriority.Camera.Value, function()
camera.CFrame = CFrame.new(head.Position - Vector3.new(0, 8, 10)) * currentRotation
camera.Focus = CFrame.new(currentRotation * Vector3.new(0, 0, -10))
end)
end

KeyboardEnabled

只读
未复制
读取并联

该属性描述了用户的设备是否有可用的键盘。当用户的设备具有可用键盘时,此属性为 true ;当它没有时,为 false

它可以用于确定用户是否有可用的键盘 - 这可能很重要,如果你想检查是否可以使用 UserInputService:IsKeyDown()UserInputService:GetKeysPressed() 来检查键盘输入。

由于 UserInputService 仅为客户端,此属性只能在 LocalScript 中使用。

代码示例

This example prints "The user's device has an available keyboard!" if KeyboardEnabled is true and "The user's device does not have an available keyboard!" if KeyboardEnabled is false.

Check if Keyboard is Enabled

local UserInputService = game:GetService("UserInputService")
if UserInputService.KeyboardEnabled then
print("The user's device has an available keyboard!")
else
print("The user's device does not have an available keyboard!")
end

MouseBehavior

读取并联

这个属性设置了用户的鼠标如何根据 Enum.MouseBehavior 枚列行为。它可以设置为三个值:

该属性的值不会影响事件跟踪鼠标移动的灵敏度。例如, GetMouseDelta 返回无论鼠标是否锁定或能够自由移动到用户屏幕周围的同一 Vector2 屏幕位置,以像素计算。因结果,控制相机的默认脚本不受此属性影响。

如果启用了 GuiButtonModalGuiButton.Visible ,该属性将被覆盖,除非玩家的右键按钮向下。

请注意,如果鼠标被锁定,UserInputService.InputChanged 仍会在玩家移动鼠标时发射,并将传递Delta,该鼠标试图移动的。此外,如果玩家被踢出游戏,鼠标将被强行解锁。

由于 UserInputService 仅为客户端,此属性只能在 LocalScript 中使用。

代码示例

This example creates a binoculars script that decreases the player's FieldOfView() and MouseDeltaSensitivity() when a player with a MouseEnabled() left mouse clicks. The script also points the player's Camera towards the Vector3 world position of the mouse click.

When the player left mouse clicks again, the player's camera reverts back to the a custom Enum.CameraType with the same field of view and CFrame() as before the player zoomed in with the script.

While the player uses the binoculars, the script locks the player's mouse to the center of the screen by setting the player's MouseBehavior() to LockCenter. The player's camera moves when the player moves their mouse according to the InputObject.Delta property passed by InputChanged() indicating the mouse's Vector2 change in screen position.

In order for this example to work as expected, it should be placed in a LocalScript.

Create a Binoculars Script

local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local character = player.CharacterAdded:Wait()
local head = character:WaitForChild("Head", false)
local mouse = player:GetMouse()
local zoomed = false
local camera = game.Workspace.CurrentCamera
local target = nil
local originalProperties = {
FieldOfView = nil,
_CFrame = nil,
MouseBehavior = nil,
MouseDeltaSensitivity = nil,
}
local AngleX, TargetAngleX = 0, 0
local AngleY, TargetAngleY = 0, 0
-- Reset camera back to CFrame and FieldOfView before zoom
local function ResetCamera()
target = nil
camera.CameraType = Enum.CameraType.Custom
camera.CFrame = originalProperties._CFrame
camera.FieldOfView = originalProperties.FieldOfView
UserInputService.MouseBehavior = originalProperties.MouseBehavior
UserInputService.MouseDeltaSensitivity = originalProperties.MouseDeltaSensitivity
end
local function ZoomCamera()
-- Allow camera to be changed by script
camera.CameraType = Enum.CameraType.Scriptable
-- Store camera properties before zoom
originalProperties._CFrame = camera.CFrame
originalProperties.FieldOfView = camera.FieldOfView
originalProperties.MouseBehavior = UserInputService.MouseBehavior
originalProperties.MouseDeltaSensitivity = UserInputService.MouseDeltaSensitivity
-- Zoom camera
target = mouse.Hit.Position
local eyesight = head.Position
camera.CFrame = CFrame.new(eyesight, target)
camera.Focus = CFrame.new(target)
camera.FieldOfView = 10
-- Lock and slow down mouse
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
UserInputService.MouseDeltaSensitivity = 1
-- Reset zoom angles
AngleX, TargetAngleX = 0, 0
AngleY, TargetAngleY = 0, 0
end
-- Toggle camera zoom/unzoom
local function MouseClick()
if zoomed then
-- Unzoom camera
ResetCamera()
else
-- Zoom in camera
ZoomCamera()
end
zoomed = not zoomed
end
local function MouseMoved(input)
if zoomed then
local sensitivity = 0.6 -- anything higher would make looking up and down harder; recommend anything between 0~1
local smoothness = 0.05 -- recommend anything between 0~1
local delta = Vector2.new(input.Delta.x / sensitivity, input.Delta.y / sensitivity) * smoothness
local X = TargetAngleX - delta.y
local Y = TargetAngleY - delta.x
TargetAngleX = (X >= 80 and 80) or (X <= -80 and -80) or X
TargetAngleY = (Y >= 80 and 80) or (Y <= -80 and -80) or Y
AngleX = AngleX + (TargetAngleX - AngleX) * 0.35
AngleY = AngleY + (TargetAngleY - AngleY) * 0.15
camera.CFrame = CFrame.new(head.Position, target)
* CFrame.Angles(0, math.rad(AngleY), 0)
* CFrame.Angles(math.rad(AngleX), 0, 0)
end
end
local function InputBegan(input, _gameProcessedEvent)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
MouseClick()
end
end
local function InputChanged(input, _gameProcessedEvent)
if input.UserInputType == Enum.UserInputType.MouseMovement then
MouseMoved(input)
end
end
if UserInputService.MouseEnabled then
UserInputService.InputBegan:Connect(InputBegan)
UserInputService.InputChanged:Connect(InputChanged)
end

By default, Roblox relies on a LocalScript to control the user's camera. However, this script can be overridden with a custom CameraScript. The example below demonstrates how to create a custom script to control the user's camera using many of the UserInputService events.

The script is broken into two parts:

  1. Mobile camera events, which rely on touch events
  2. Non-mobile camera events, which rely on keyboard input and tracking the user's movement

First, the camera script needs utility functions to setup the camera and set its Camera.CameraType to Scriptable so that the script can control the camera. It also needs a function to update the camera when it moves, rotates, and zooms.

Using touch events allows us to track user input as they interact with the touchscreen on their mobile device. These events allow us to handle camera movement, rotation, and zoom.

The second half of the code sample adds camera support for players on desktop devices. When input begans, the function Input() checks that the state of the input is Enum.UserInputState.Begin to ignore all keypress inputs other than when the user first presses a key down. When the user presses I and O the camera zooms in and out. When the presses down and moves their left mouse button, the script locks the player's mouse by changing the UserInputService.MouseBehavior property. The camera rotates according to the mouse's change in screen position. When the player moves their character, the camera moves with them.

All of the parts discussed above are combined and shown in the code sample below.

Create a Custom CameraScript

local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local camera = workspace.CurrentCamera
local player = Players.LocalPlayer
local character = player.CharacterAdded:Wait()
local torso = character:WaitForChild("HumanoidRootPart")
local playerPosition = torso.Position
local default_CameraPosition = torso.Position
local default_CameraRotation = Vector2.new(0, math.rad(-60))
local default_CameraZoom = 15
local cameraPosition = default_CameraPosition
local cameraRotation = default_CameraRotation
local cameraZoom = default_CameraZoom
local cameraZoomBounds = nil -- {10,200}
local cameraRotateSpeed = 10
local cameraMouseRotateSpeed = 0.25
local cameraTouchRotateSpeed = 10
local function SetCameraMode()
camera.CameraType = "Scriptable"
camera.FieldOfView = 80
camera.CameraSubject = nil
end
local function UpdateCamera()
SetCameraMode()
local cameraRotationCFrame = CFrame.Angles(0, cameraRotation.X, 0) * CFrame.Angles(cameraRotation.Y, 0, 0)
camera.CFrame = cameraRotationCFrame + cameraPosition + cameraRotationCFrame * Vector3.new(0, 0, cameraZoom)
camera.Focus = camera.CFrame - Vector3.new(0, camera.CFrame.p.Y, 0)
end
local lastTouchTranslation = nil
local function TouchMove(_touchPositions, totalTranslation, _velocity, state)
if state == Enum.UserInputState.Change or state == Enum.UserInputState.End then
local difference = totalTranslation - lastTouchTranslation
cameraPosition = cameraPosition + Vector3.new(difference.X, 0, difference.Y)
UpdateCamera()
end
lastTouchTranslation = totalTranslation
end
local lastTouchRotation = nil
local function TouchRotate(_touchPositions, rotation, _velocity, state)
if state == Enum.UserInputState.Change or state == Enum.UserInputState.End then
local difference = rotation - lastTouchRotation
cameraRotation = cameraRotation
+ Vector2.new(-difference, 0) * math.rad(cameraTouchRotateSpeed * cameraRotateSpeed)
UpdateCamera()
end
lastTouchRotation = rotation
end
local lastTouchScale = nil
local function TouchZoom(_touchPositions, scale, _velocity, state)
if state == Enum.UserInputState.Change or state == Enum.UserInputState.End then
local difference = scale - lastTouchScale
cameraZoom = cameraZoom * (1 + difference)
if cameraZoomBounds ~= nil then
cameraZoom = math.min(math.max(cameraZoom, cameraZoomBounds[1]), cameraZoomBounds[2])
else
cameraZoom = math.max(cameraZoom, 0)
end
UpdateCamera()
end
lastTouchScale = scale
end
local function Input(inputObject)
if inputObject.UserInputType == Enum.UserInputType.Keyboard then
if inputObject.UserInputState == Enum.UserInputState.Begin then
-- (I) Zoom In
if inputObject.KeyCode == Enum.KeyCode.I then
cameraZoom = cameraZoom - 15
elseif inputObject.KeyCode == Enum.KeyCode.O then
cameraZoom = cameraZoom + 15
end
-- (O) Zoom Out
if cameraZoomBounds ~= nil then
cameraZoom = math.min(math.max(cameraZoom, cameraZoomBounds[1]), cameraZoomBounds[2])
else
cameraZoom = math.max(cameraZoom, 0)
end
UpdateCamera()
end
end
local pressed = UserInputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton1)
if pressed then
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCurrentPosition
local rotation = UserInputService:GetMouseDelta()
cameraRotation = cameraRotation + rotation * math.rad(cameraMouseRotateSpeed)
else
UserInputService.MouseBehavior = Enum.MouseBehavior.Default
end
end
local function PlayerChanged()
local movement = torso.Position - playerPosition
cameraPosition = cameraPosition + movement
playerPosition = torso.Position
UpdateCamera()
end
-- Determine whether the user is on a mobile device
if UserInputService.TouchEnabled then
-- The user is on a mobile device, use Touch events
UserInputService.TouchPan:Connect(TouchMove)
UserInputService.TouchRotate:Connect(TouchRotate)
UserInputService.TouchPinch:Connect(TouchZoom)
else
-- The user is not on a mobile device use Input events
UserInputService.InputBegan:Connect(Input)
UserInputService.InputChanged:Connect(Input)
UserInputService.InputEnded:Connect(Input)
-- Camera controlled by player movement
task.wait(2)
RunService:BindToRenderStep("PlayerChanged", Enum.RenderPriority.Camera.Value - 1, PlayerChanged)
end

MouseDeltaSensitivity

未复制
读取并联

该属性决定了用户的 Mouse 的灵敏度。

灵敏度决定了物理鼠标的移动转换到游戏中鼠标的移动程度。这可以用来调整如何敏感事件跟踪鼠标移动,例如 GetMouseDelta , 是否跟随鼠标移动。

该属性不会影响鼠标标志的移动。它也不会影响客户端 设置 菜单的 设置 选项卡中找到的 相机灵敏度 设置,该设置也调整了事件跟踪鼠标移动的灵敏度。

该属性的最大值为 10 并且最小值为 0。较低的值对应较低的灵敏度,较高的值对应更高的灵敏度。

当灵敏度为 0 时,跟踪鼠标移动的事件仍会发射,但所有显示鼠标位置变更的参数和属性都会返回 Vector2.new()Vector3.new()InputObject.Delta 的情况下。例如,GetMouseDelta 总是会返回(0,0)。

代码示例

This example creates a binoculars script that decreases the player's FieldOfView() and MouseDeltaSensitivity() when a player with a MouseEnabled() left mouse clicks. The script also points the player's Camera towards the Vector3 world position of the mouse click.

When the player left mouse clicks again, the player's camera reverts back to the a custom Enum.CameraType with the same field of view and CFrame() as before the player zoomed in with the script.

While the player uses the binoculars, the script locks the player's mouse to the center of the screen by setting the player's MouseBehavior() to LockCenter. The player's camera moves when the player moves their mouse according to the InputObject.Delta property passed by InputChanged() indicating the mouse's Vector2 change in screen position.

In order for this example to work as expected, it should be placed in a LocalScript.

Create a Binoculars Script

local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local character = player.CharacterAdded:Wait()
local head = character:WaitForChild("Head", false)
local mouse = player:GetMouse()
local zoomed = false
local camera = game.Workspace.CurrentCamera
local target = nil
local originalProperties = {
FieldOfView = nil,
_CFrame = nil,
MouseBehavior = nil,
MouseDeltaSensitivity = nil,
}
local AngleX, TargetAngleX = 0, 0
local AngleY, TargetAngleY = 0, 0
-- Reset camera back to CFrame and FieldOfView before zoom
local function ResetCamera()
target = nil
camera.CameraType = Enum.CameraType.Custom
camera.CFrame = originalProperties._CFrame
camera.FieldOfView = originalProperties.FieldOfView
UserInputService.MouseBehavior = originalProperties.MouseBehavior
UserInputService.MouseDeltaSensitivity = originalProperties.MouseDeltaSensitivity
end
local function ZoomCamera()
-- Allow camera to be changed by script
camera.CameraType = Enum.CameraType.Scriptable
-- Store camera properties before zoom
originalProperties._CFrame = camera.CFrame
originalProperties.FieldOfView = camera.FieldOfView
originalProperties.MouseBehavior = UserInputService.MouseBehavior
originalProperties.MouseDeltaSensitivity = UserInputService.MouseDeltaSensitivity
-- Zoom camera
target = mouse.Hit.Position
local eyesight = head.Position
camera.CFrame = CFrame.new(eyesight, target)
camera.Focus = CFrame.new(target)
camera.FieldOfView = 10
-- Lock and slow down mouse
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
UserInputService.MouseDeltaSensitivity = 1
-- Reset zoom angles
AngleX, TargetAngleX = 0, 0
AngleY, TargetAngleY = 0, 0
end
-- Toggle camera zoom/unzoom
local function MouseClick()
if zoomed then
-- Unzoom camera
ResetCamera()
else
-- Zoom in camera
ZoomCamera()
end
zoomed = not zoomed
end
local function MouseMoved(input)
if zoomed then
local sensitivity = 0.6 -- anything higher would make looking up and down harder; recommend anything between 0~1
local smoothness = 0.05 -- recommend anything between 0~1
local delta = Vector2.new(input.Delta.x / sensitivity, input.Delta.y / sensitivity) * smoothness
local X = TargetAngleX - delta.y
local Y = TargetAngleY - delta.x
TargetAngleX = (X >= 80 and 80) or (X <= -80 and -80) or X
TargetAngleY = (Y >= 80 and 80) or (Y <= -80 and -80) or Y
AngleX = AngleX + (TargetAngleX - AngleX) * 0.35
AngleY = AngleY + (TargetAngleY - AngleY) * 0.15
camera.CFrame = CFrame.new(head.Position, target)
* CFrame.Angles(0, math.rad(AngleY), 0)
* CFrame.Angles(math.rad(AngleX), 0, 0)
end
end
local function InputBegan(input, _gameProcessedEvent)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
MouseClick()
end
end
local function InputChanged(input, _gameProcessedEvent)
if input.UserInputType == Enum.UserInputType.MouseMovement then
MouseMoved(input)
end
end
if UserInputService.MouseEnabled then
UserInputService.InputBegan:Connect(InputBegan)
UserInputService.InputChanged:Connect(InputChanged)
end

MouseEnabled

只读
未复制
读取并联

该属性描述了用户的设备是否有可用的鼠标。当用户的设备有可用的鼠标时,此属性为 true ;当它没有时,为 false


local UserInputService = game:GetService("UserInputService")
if UserInputService.MouseEnabled then
print("The user's device has an available mouse!")
else
print("The user's device does not have an available mouse!")
end

在使用 UserInputService 鼠标功能之前,例如 UserInputService:GetMouseLocation() ,必须检查此项。

由于 UserInputService 仅为客户端,此属性只能在 LocalScript 中使用。

还见:

代码示例

This example creates a binoculars script that decreases the player's FieldOfView() and MouseDeltaSensitivity() when a player with a MouseEnabled() left mouse clicks. The script also points the player's Camera towards the Vector3 world position of the mouse click.

When the player left mouse clicks again, the player's camera reverts back to the a custom Enum.CameraType with the same field of view and CFrame() as before the player zoomed in with the script.

While the player uses the binoculars, the script locks the player's mouse to the center of the screen by setting the player's MouseBehavior() to LockCenter. The player's camera moves when the player moves their mouse according to the InputObject.Delta property passed by InputChanged() indicating the mouse's Vector2 change in screen position.

In order for this example to work as expected, it should be placed in a LocalScript.

Create a Binoculars Script

local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local character = player.CharacterAdded:Wait()
local head = character:WaitForChild("Head", false)
local mouse = player:GetMouse()
local zoomed = false
local camera = game.Workspace.CurrentCamera
local target = nil
local originalProperties = {
FieldOfView = nil,
_CFrame = nil,
MouseBehavior = nil,
MouseDeltaSensitivity = nil,
}
local AngleX, TargetAngleX = 0, 0
local AngleY, TargetAngleY = 0, 0
-- Reset camera back to CFrame and FieldOfView before zoom
local function ResetCamera()
target = nil
camera.CameraType = Enum.CameraType.Custom
camera.CFrame = originalProperties._CFrame
camera.FieldOfView = originalProperties.FieldOfView
UserInputService.MouseBehavior = originalProperties.MouseBehavior
UserInputService.MouseDeltaSensitivity = originalProperties.MouseDeltaSensitivity
end
local function ZoomCamera()
-- Allow camera to be changed by script
camera.CameraType = Enum.CameraType.Scriptable
-- Store camera properties before zoom
originalProperties._CFrame = camera.CFrame
originalProperties.FieldOfView = camera.FieldOfView
originalProperties.MouseBehavior = UserInputService.MouseBehavior
originalProperties.MouseDeltaSensitivity = UserInputService.MouseDeltaSensitivity
-- Zoom camera
target = mouse.Hit.Position
local eyesight = head.Position
camera.CFrame = CFrame.new(eyesight, target)
camera.Focus = CFrame.new(target)
camera.FieldOfView = 10
-- Lock and slow down mouse
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
UserInputService.MouseDeltaSensitivity = 1
-- Reset zoom angles
AngleX, TargetAngleX = 0, 0
AngleY, TargetAngleY = 0, 0
end
-- Toggle camera zoom/unzoom
local function MouseClick()
if zoomed then
-- Unzoom camera
ResetCamera()
else
-- Zoom in camera
ZoomCamera()
end
zoomed = not zoomed
end
local function MouseMoved(input)
if zoomed then
local sensitivity = 0.6 -- anything higher would make looking up and down harder; recommend anything between 0~1
local smoothness = 0.05 -- recommend anything between 0~1
local delta = Vector2.new(input.Delta.x / sensitivity, input.Delta.y / sensitivity) * smoothness
local X = TargetAngleX - delta.y
local Y = TargetAngleY - delta.x
TargetAngleX = (X >= 80 and 80) or (X <= -80 and -80) or X
TargetAngleY = (Y >= 80 and 80) or (Y <= -80 and -80) or Y
AngleX = AngleX + (TargetAngleX - AngleX) * 0.35
AngleY = AngleY + (TargetAngleY - AngleY) * 0.15
camera.CFrame = CFrame.new(head.Position, target)
* CFrame.Angles(0, math.rad(AngleY), 0)
* CFrame.Angles(math.rad(AngleX), 0, 0)
end
end
local function InputBegan(input, _gameProcessedEvent)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
MouseClick()
end
end
local function InputChanged(input, _gameProcessedEvent)
if input.UserInputType == Enum.UserInputType.MouseMovement then
MouseMoved(input)
end
end
if UserInputService.MouseEnabled then
UserInputService.InputBegan:Connect(InputBegan)
UserInputService.InputChanged:Connect(InputChanged)
end

MouseIcon

ContentId
读取并联

MouseIcon 属性决定使用作指针的图像。如果为空,默认使用箭头。当鼠标悬停在某些用户界面对象上,例如 ImageButton , TextButton , TextBoxProximityPrompt 时,此图像将被替换并暂时忽略。

要完全隐藏鼠标,请不要使用透明图像。相反,将 设置为 false。

代码示例

This example changes the user mouse icon to look like a dragon image.

UserInputService.MouseIcon

local UserInputService = game:GetService("UserInputService")
-- In order to restore the cursor to what it was set to previously, it will need to be saved to a variable
local savedCursor = nil
local function setTemporaryCursor(cursor: string)
-- Only update the saved cursor if it's not currently saved
if not savedCursor then
savedCursor = UserInputService.MouseIcon
end
UserInputService.MouseIcon = cursor
end
local function clearTemporaryCursor()
-- Only restore the mouse cursor if there's a saved cursor to restore
if savedCursor then
UserInputService.MouseIcon = savedCursor
-- Don't restore the same cursor twice (might overwrite another script)
savedCursor = nil
end
end
setTemporaryCursor("http://www.roblox.com/asset?id=163023520")
print(UserInputService.MouseIcon)
clearTemporaryCursor()
print(UserInputService.MouseIcon)

MouseIconEnabled

读取并联

该属性决定是否显示 图标,当鼠标的图标可见时,当 它不可见时。

例如,下面的代码片段隐藏了鼠标的标志。


local UserInputService = game:GetService("UserInputService")
UserInputService.MouseIconEnabled = false

由于 UserInputService 仅为客户端,此属性只能在 LocalScript 中使用。

代码示例

This example hides the mouse icon while the player beings using their keyboard, such as to chat or enter text into a TextBox. The mouse icon reappears when the user resumes mouse input.

This uses the LastInputType() event to determine when the user begins keyboard input and mouse input - based on the value of the lastInputType argument.

In order for this example to work as expected, it should be placed in a LocalScript.

Hide Mouse During Keyboard Input

local UserInputService = game:GetService("UserInputService")
local mouseInput = {
Enum.UserInputType.MouseButton1,
Enum.UserInputType.MouseButton2,
Enum.UserInputType.MouseButton3,
Enum.UserInputType.MouseMovement,
Enum.UserInputType.MouseWheel,
}
local keyboard = Enum.UserInputType.Keyboard
local function toggleMouse(lastInputType)
if lastInputType == keyboard then
UserInputService.MouseIconEnabled = false
return
end
for _, mouse in pairs(mouseInput) do
if lastInputType == mouse then
UserInputService.MouseIconEnabled = true
return
end
end
end
UserInputService.LastInputTypeChanged:Connect(toggleMouse)

OnScreenKeyboardPosition

只读
未复制
读取并联

此属性描述屏幕上键盘的位置以像素为单位。键盘的位置为 Vector2.new(0, 0) 当它不可见时。

由于 UserInputService 仅为客户端,此属性只能在 LocalScriptScript 中使用,其中 RunContext 设置为 Enum.RunContext.Client

还见 OnScreenKeyboardVisibleOnScreenKeyboardSize

代码示例

This example prints the position of the player's on-screen keyboard.

UserInputService.OnScreenKeyboardPosition

local UserInputService = game:GetService("UserInputService")
print(UserInputService.OnScreenKeyboardPosition)

OnScreenKeyboardSize

只读
未复制
读取并联

此属性描述屏幕上键盘的像素大小。当键盘不可见时,键盘的大小为 Vector2.new(0, 0)

由于 UserInputService 仅为客户端,此属性只能在 LocalScriptScript 中使用,其中 RunContext 设置为 Enum.RunContext.Client

还见 OnScreenKeyboardVisibleOnScreenKeyboardPosition

OnScreenKeyboardVisible

只读
未复制
读取并联

此属性描述了屏幕上的键盘是否目前在用户的屏幕上可见。

由于 UserInputService 仅为客户端,此属性只能在 LocalScriptScript 中使用,其中 RunContext 设置为 Enum.RunContext.Client

还见 OnScreenKeyboardSizeOnScreenKeyboardPosition

TouchEnabled

只读
未复制
读取并联

该属性描述了用户当前设备是否有可用的触摸屏。

属性用于确定用户的设备是否具有触摸屏,因此触摸事件是否会发触发。如果触摸启用是真的,你可以使用用户输入服务事件,例如 UserInputService.TouchStartedUserInputService.TouchEnded 来跟踪用户何时开始和停止触摸他们设备的屏幕。

下面的代码片段打印用户的设备是否有触摸屏。


local UserInputService = game:GetService("UserInputService")
if UserInputService.TouchEnabled then
print("The user's device has a touchscreen!")
else
print("The user's device does not have a touchscreen!")
end

还见:

代码示例

By default, Roblox relies on a LocalScript to control the user's camera. However, this script can be overridden with a custom CameraScript. The example below demonstrates how to create a custom script to control the user's camera using many of the UserInputService events.

The script is broken into two parts:

  1. Mobile camera events, which rely on touch events
  2. Non-mobile camera events, which rely on keyboard input and tracking the user's movement

First, the camera script needs utility functions to setup the camera and set its Camera.CameraType to Scriptable so that the script can control the camera. It also needs a function to update the camera when it moves, rotates, and zooms.

Using touch events allows us to track user input as they interact with the touchscreen on their mobile device. These events allow us to handle camera movement, rotation, and zoom.

The second half of the code sample adds camera support for players on desktop devices. When input begans, the function Input() checks that the state of the input is Enum.UserInputState.Begin to ignore all keypress inputs other than when the user first presses a key down. When the user presses I and O the camera zooms in and out. When the presses down and moves their left mouse button, the script locks the player's mouse by changing the UserInputService.MouseBehavior property. The camera rotates according to the mouse's change in screen position. When the player moves their character, the camera moves with them.

All of the parts discussed above are combined and shown in the code sample below.

Create a Custom CameraScript

local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local camera = workspace.CurrentCamera
local player = Players.LocalPlayer
local character = player.CharacterAdded:Wait()
local torso = character:WaitForChild("HumanoidRootPart")
local playerPosition = torso.Position
local default_CameraPosition = torso.Position
local default_CameraRotation = Vector2.new(0, math.rad(-60))
local default_CameraZoom = 15
local cameraPosition = default_CameraPosition
local cameraRotation = default_CameraRotation
local cameraZoom = default_CameraZoom
local cameraZoomBounds = nil -- {10,200}
local cameraRotateSpeed = 10
local cameraMouseRotateSpeed = 0.25
local cameraTouchRotateSpeed = 10
local function SetCameraMode()
camera.CameraType = "Scriptable"
camera.FieldOfView = 80
camera.CameraSubject = nil
end
local function UpdateCamera()
SetCameraMode()
local cameraRotationCFrame = CFrame.Angles(0, cameraRotation.X, 0) * CFrame.Angles(cameraRotation.Y, 0, 0)
camera.CFrame = cameraRotationCFrame + cameraPosition + cameraRotationCFrame * Vector3.new(0, 0, cameraZoom)
camera.Focus = camera.CFrame - Vector3.new(0, camera.CFrame.p.Y, 0)
end
local lastTouchTranslation = nil
local function TouchMove(_touchPositions, totalTranslation, _velocity, state)
if state == Enum.UserInputState.Change or state == Enum.UserInputState.End then
local difference = totalTranslation - lastTouchTranslation
cameraPosition = cameraPosition + Vector3.new(difference.X, 0, difference.Y)
UpdateCamera()
end
lastTouchTranslation = totalTranslation
end
local lastTouchRotation = nil
local function TouchRotate(_touchPositions, rotation, _velocity, state)
if state == Enum.UserInputState.Change or state == Enum.UserInputState.End then
local difference = rotation - lastTouchRotation
cameraRotation = cameraRotation
+ Vector2.new(-difference, 0) * math.rad(cameraTouchRotateSpeed * cameraRotateSpeed)
UpdateCamera()
end
lastTouchRotation = rotation
end
local lastTouchScale = nil
local function TouchZoom(_touchPositions, scale, _velocity, state)
if state == Enum.UserInputState.Change or state == Enum.UserInputState.End then
local difference = scale - lastTouchScale
cameraZoom = cameraZoom * (1 + difference)
if cameraZoomBounds ~= nil then
cameraZoom = math.min(math.max(cameraZoom, cameraZoomBounds[1]), cameraZoomBounds[2])
else
cameraZoom = math.max(cameraZoom, 0)
end
UpdateCamera()
end
lastTouchScale = scale
end
local function Input(inputObject)
if inputObject.UserInputType == Enum.UserInputType.Keyboard then
if inputObject.UserInputState == Enum.UserInputState.Begin then
-- (I) Zoom In
if inputObject.KeyCode == Enum.KeyCode.I then
cameraZoom = cameraZoom - 15
elseif inputObject.KeyCode == Enum.KeyCode.O then
cameraZoom = cameraZoom + 15
end
-- (O) Zoom Out
if cameraZoomBounds ~= nil then
cameraZoom = math.min(math.max(cameraZoom, cameraZoomBounds[1]), cameraZoomBounds[2])
else
cameraZoom = math.max(cameraZoom, 0)
end
UpdateCamera()
end
end
local pressed = UserInputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton1)
if pressed then
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCurrentPosition
local rotation = UserInputService:GetMouseDelta()
cameraRotation = cameraRotation + rotation * math.rad(cameraMouseRotateSpeed)
else
UserInputService.MouseBehavior = Enum.MouseBehavior.Default
end
end
local function PlayerChanged()
local movement = torso.Position - playerPosition
cameraPosition = cameraPosition + movement
playerPosition = torso.Position
UpdateCamera()
end
-- Determine whether the user is on a mobile device
if UserInputService.TouchEnabled then
-- The user is on a mobile device, use Touch events
UserInputService.TouchPan:Connect(TouchMove)
UserInputService.TouchRotate:Connect(TouchRotate)
UserInputService.TouchPinch:Connect(TouchZoom)
else
-- The user is not on a mobile device use Input events
UserInputService.InputBegan:Connect(Input)
UserInputService.InputChanged:Connect(Input)
UserInputService.InputEnded:Connect(Input)
-- Camera controlled by player movement
task.wait(2)
RunService:BindToRenderStep("PlayerChanged", Enum.RenderPriority.Camera.Value - 1, PlayerChanged)
end

VREnabled

只读
未复制
读取并联

该属性描述用户是否使用虚拟现实(VR)设备。

如果启用了 VR 设备,您可以通过函数如 UserInputService:GetUserCFrame() 与其位置和移动进行互动。您还可以使用 UserInputService.UserCFrameChanged 事件反应虚拟现实设备的移动。


local UserInputService = game:GetService("UserInputService")
local isUsingVR = UserInputService.VREnabled
if isUsingVR then
print("User is using a VR headset!")
else
print("User is not using a VR headset!")
end

由于 UserInputService 仅为客户端,此属性只能在 LocalScript 中使用。

还见:

代码示例

This example demonstrates how to implement a head tracking script that mirrors the movement of a virtual reality (VR) headset (the user's actual head) to their in-game character's head.

The example first check if the user is using a VR device by checking the value of the VREnabled() property. This example only works if the user is using a VR headset.

To determine the initial CFrame of the character's head, the code sample calls GetUserCFrame() and passes Enum.UserCFrame.Head as the argument.

To update the head's CFrame whenever the user's VR headset moves, the example connects the VRService.UserCFrameChanged event to the TrackHead() function. When the event fires to indicate that a VR device moved, TrackHead() checks if the headset moved. If the headset moved, the function updates the CFrame of the character's head to the CFrame value provided as an argument.

As the UserCFrame enum also tracks VR left and right hand devices, the concept of VR device tracking can be expanded to other character bodyparts.

In order for the example to work as expected, it must be placed in a LocalScript.

VR Head Tracking

local VRService = game:GetService("VRService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local character = player.CharacterAdded:Wait()
local head = character:WaitForChild("Head")
local function TrackHead(inputType, value)
if inputType == Enum.UserCFrame.Head then
head.CFrame = value
end
end
if VRService.VREnabled then
-- Set the initial CFrame
head.CFrame = VRService:GetUserCFrame(Enum.UserCFrame.Head)
-- Track VR headset movement and mirror for character's head
VRService.UserCFrameChanged:Connect(TrackHead)
end

方法

GamepadSupports

此函数返回给定的 Enum.UserInputType 游戏手柄是否支持与给定的 Enum.KeyCode 相对应的按钮。该函数用于确定有效的游戏手柄输入。

要确定哪些 Enum.UserInputType 游戏手柄连接,请使用 UserInputService:GetConnectedGamepads()

由于 UserInputService 仅为客户端,此函数只能在 LocalScript 中使用。

还见:

参数

gamepadNum: Enum.UserInputType

游戏手柄的 Enum.UserInputType

默认值:""
gamepadKeyCode: Enum.KeyCode

问题中的按钮的 Enum.KeyCode

默认值:""

返回

是否给定的游戏手柄支持与给定的Enum.KeyCode相对应的按钮。

代码示例

This example binds the ButtonX key to action if it is supported by controller (Gamepad1). If bound, pressing the X Button invokes the action() function, which prints "Action".

Binding Functions to Gamepad Controls

local UserInputService = game:GetService("UserInputService")
local ContextActionService = game:GetService("ContextActionService")
local controller = Enum.UserInputType.Gamepad1
local buttonX = Enum.KeyCode.ButtonX
local function isSupported(gamepad, keycode)
return UserInputService:GamepadSupports(gamepad, keycode)
end
local function action()
print("Action")
end
if isSupported(controller, buttonX) then
ContextActionService:BindAction("sample action", action, false, buttonX)
end

GetConnectedGamepads

此函数返回当前连接的 Enum.UserInputType 游戏手柄阵列。如果没有连接游戏手柄,这个阵列将为空。此外,它只返回游戏手柄的 UserInputType 对象。例实例,这个事件将返回连接的 Gamepad1 对象,但不是键盘对象。

例如,以下代码片段检索连接的游戏手柄,并将它们存储在名为 connectedGamepads 的变量中。


local UserInputService = game:GetService("UserInputService")
local connectedGamepads = UserInputService:GetConnectedGamepads()

要检查特定游戏手柄是否连接,请使用 UserInputService:GetGamepadConnected()

由于 UserInputService 仅为客户端,此函数只能在 LocalScript 中使用。

还见:


返回

一个与连接到用户设备的游戏手柄相对应的 UserInputTypes 阵列。

代码示例

If you are using the default controls, you do not need to worry about this. If you're creating a custom script for handling gamepad controls, this is a good template for retrieving which gamepad enum you should use as the primary gamepad controller.

How to Set the Active Gamepad for Input

local UserInputService = game:GetService("UserInputService")
local function getActiveGamepad()
local activeGamepad = nil
local connectedGamepads = UserInputService:GetConnectedGamepads()
if #connectedGamepads > 0 then
for _, gamepad in connectedGamepads do
if activeGamepad == nil or gamepad.Value < activeGamepad.Value then
activeGamepad = gamepad
end
end
end
if activeGamepad == nil then -- Nothing is connected; set up for "Gamepad1"
activeGamepad = Enum.UserInputType.Gamepad1
end
return activeGamepad
end
if UserInputService.GamepadEnabled then
local activeGamepad = getActiveGamepad()
print(activeGamepad)
end

GetDeviceAcceleration

获取设备加速函数确定用户设备的当前加速。它返回一个 InputObject 描述设备当前加速的文本。

为了使此功能正常运行,用户的设备必须配备加速器。要检查用户的设备是否具有启用加速器,您可以检查 UserInputService.AccelerometerEnabled 属性。

如果你想在用户的设备加速更改时跟踪,你可以使用 UserInputService.DeviceAccelerationChanged 事件。

由于它只能在本地发射,它只能在 LocalScript 中使用。


返回

代码示例

This example checks if a user's device has an enabled accelerometer. If it does, the example prints the current acceleration of the device. If not, the example prints:

Cannot get device acceleration because device does not have an enabled accelerometer!

Print Device Acceleration

local UserInputService = game:GetService("UserInputService")
local accelerometerEnabled = UserInputService.AccelerometerEnabled
if accelerometerEnabled then
local acceleration = UserInputService:GetDeviceAcceleration().Position
print(acceleration)
else
print("Cannot get device acceleration because device does not have an enabled accelerometer!")
end

GetDeviceGravity

该函数返回一个 InputObject 描述设备当前重力向量的函矢量力。

重力向量由设备对重力世界力的相对位置决定。例实例,如果设备完全垂直(竖向),重力向量是 Vector3.new(0, 0, -9.18) 。如果设备的左侧指向下,向量是 Vector3.new(9.81, 0, 0)。最后,如果设备的后面指向下,向量是 Vector3.new(0, -9.81, 0)。

该函数可能用于启用用户的设备在游戏中影响或控制重力或移动游戏对象,例如球。

重力仅用于启用陀螺仪的设备的玩家 - 例如移动设备。

要检查用户的设备是否具有启用陀螺仪,请检查 UserInputService.GyroscopeEnabled 的值。如果设备具有启用陀螺仪,您还可以使用 UserInputService.DeviceGravityChanged 事件来跟踪用户设备上重力力量的变化。

由于 UserInputService 仅为客户端,此函数只能在 LocalScript 中使用。


返回

代码示例

Using the Gyroscope gives us the down direction for the player's device. We can use this to move objects in the game world. This example implements a level where the bubble will move along the X and Z axes depending on the device's current gryoscope position in X and Z.

Moving Objects with the Gyroscope

local UserInputService = game:GetService("UserInputService")
local bubble = script.Parent:WaitForChild("Bubble")
local camera = workspace.CurrentCamera
camera.CameraType = Enum.CameraType.Scriptable
camera.CFrame = CFrame.new(0, 20, 0) * CFrame.Angles(-math.pi / 2, 0, 0)
if UserInputService.GyroscopeEnabled then
-- Bind event to when gyroscope detects change
UserInputService.DeviceGravityChanged:Connect(function(accel)
-- Move the bubble in the world based on the gyroscope data
bubble.Position = Vector3.new(-8 * accel.Position.X, 1.8, -8 * accel.Position.Z)
end)
end

GetDeviceRotation

该函数返回一个 和一个 描述设备当前旋转向矢量力的 。

这被发射到一个输入对象。输入对象的 位置 属性是一个 Enum.InputType.Gyroscope ,用于跟踪每个本地设备轴的总旋转。

设备旋转只能在具有 gyroscope 的设备上跟踪。

由于此函数是在本地发射的,它只能在 LocalScript 中使用。


返回

包含两个属性的 tuple:

  1. delta 属性描述最后发生的旋转量
  2. CFrame 是设备当前对其默认参考框的旋转。

代码示例

This example prints the current CFrame of a players device. Note that this will only work as expected if the player's device has an enabled gyroscope. If not, the example prints:

Cannot get device rotation because device does not have an enabled gyroscope!

Print Device Rotation

local UserInputService = game:GetService("UserInputService")
local gyroEnabled = UserInputService:GyroscopeEnabled()
if gyroEnabled then
local _inputObj, cframe = UserInputService:GetDeviceRotation()
print("CFrame: {", cframe, "}")
else
print("Cannot get device rotation because device does not have an enabled gyroscope!")
end

GetFocusedTextBox

此函数返回客户端目前关注的 TextBox。A TextBox 可以由用户手动选择,或使用 TextBox:CaptureFocus() 函数强制选择。如果未选择TextBox,该函数将返回nil

由于 UserInputService 仅为客户端,此函数只能在 LocalScript 中使用。

还看到也看到

返回

GetGamepadConnected

此函数返回是否连接了带有给定 Enum.UserInputType 的游戏手柄到客户端。

这可用于检查是否有特定游戏手柄,例如 'Gamepad1' 连接到客户端设备。

要检索所有连接的游戏手柄的列表,请使用 UserInputService:GetConnectedGamepads()

由于 UserInputService 仅为客户端,此函数只能在 LocalScript 中使用。

还见:

参数

gamepadNum: Enum.UserInputType

游戏手柄中的 Enum.UserInputType

默认值:""

返回

是否连接了与 Enum.UserInputType 相关的游戏手柄。

代码示例

This example returns whether Gamepad1 is connected to the client. It will print true if Gamepad1 is connected and false if Gamepad1 is not connected.

Check Whether a Gamepad is Connected

local UserInputService = game:GetService("UserInputService")
local isConnected = UserInputService:GetGamepadConnected(Enum.UserInputType.Gamepad1)
if isConnected then
print("Gamepad1 is connected to the client")
else
print("Gamepad1 is not connected to the client")
end

GetGamepadState

此函数返回给定 游戏手柄上所有可用输入的阵列,代表每个输入的最后输入状态。

要找到连接的游戏手柄的 UserInputTypes,请使用 UserInputService:GetConnectedGamepads()

由于此函数仅在本地发射,它只能在 LocalScript 中使用。

还见:

参数

gamepadNum: Enum.UserInputType

与问题的游戏手柄相对应的 Enum.UserInputType

默认值:""

返回

一个InputObjects阵列,代表给定游戏手柄的所有可用输入的当前状态。

GetImageForKeyCode

ContentId

该方法接受请求的 Enum.KeyCode 并返回与连接到的游戏手柄设备相关的图像(仅限于 Xbox、PlayStation 和 Windows)。这意味着如果连接的控制器是 Xbox 一控制器,用户看到的是 Xbox 资产。同样,如果连接的设备是 PlayStation 控制器,用户看到 PlayStation 资产。如果您想使用自定义资产,请参阅GetStringForKeyCode()

参数

keyCode: Enum.KeyCode

用于获取相关图像的 Enum.KeyCode

默认值:""

返回

ContentId

返回的图像资产 ID。

代码示例

This API returns the requested image for the given Enum.KeyCode.

UserInputService - Get Image For KeyCode

local UserInputService = game:GetService("UserInputService")
local imageLabel = script.Parent
local key = Enum.KeyCode.ButtonA
local mappedIconImage = UserInputService:GetImageForKeyCode(key)
imageLabel.Image = mappedIconImage

GetKeysPressed

该函数返回与当前按下的键相关的 InputObjects 阵列。

这个阵列可以循环以确定当前正在按下哪些键,使用 InputObject.KeyCode 值。

要检查特定键是否被按下,请使用 UserInputService:IsKeyDown()

由于 UserInputService 仅为客户端,此函数只能在 LocalScript 中使用。


返回

与当前按下的键相关的 InputObjects 阵列。

代码示例

This example demonstrates how to use the UserInputService:GetKeysPressed() function to create a combo action where the player double jumps when the player presses actionKey key (Left Shift) + Jump key (Spacebar).

The actionKey variable indicates which key, combined with the Jump key, needs to be pressed for the player to double jump.

When the player presses the Jump key, the JumpRequest() event is invoked, which is connected to the script's jumpRequest function. If the Left Shift key is pressed and the player is not already in the middle of a jump, this function sets the canDoubleJump boolean to true.

The example connects the stateChanged function to the StateChanged() event so that the function fires when their humanoid's state changes. If the state changes from Jumping to Freefall, and the canDoubleJump boolean is true, the function makes the player jump again by setting their humanoid's state back to Jumping using the ChangeState() function . The example also uses the canJump boolean variable to determine when the player is in the middle of a jump. Without this variable, the player could press the actionKey + Jump Key (spacebar) to jump endlessly without landing. When the boolean is true, the player is not jumping. If the player is not jumping, jumpRequest() checks if the actionKey is pressed and sets canJump to false. When the player lands, stateChanged() sets the variable to true.

Double Jump Key Combo

local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local actionKey = Enum.KeyCode.LeftShift
local canJump = true
local canDoubleJump = false
local function jumpRequest()
local keysPressed = UserInputService:GetKeysPressed()
for _, key in ipairs(keysPressed) do
if key.KeyCode == actionKey and canJump then
canJump = false
canDoubleJump = true
end
end
end
local function stateChanged(oldState, newState)
-- Double jump during freefall if able to
if oldState == Enum.HumanoidStateType.Jumping and newState == Enum.HumanoidStateType.Freefall and canDoubleJump then
canDoubleJump = false
task.wait(0.2)
humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
-- Allow player to jump again after they land
if oldState == Enum.HumanoidStateType.Freefall and newState == Enum.HumanoidStateType.Landed then
canJump = true
end
end
UserInputService.JumpRequest:Connect(jumpRequest)
humanoid.StateChanged:Connect(stateChanged)

GetLastInputType

该函数返回与用户最新输入相关的 'Enum.UserInputType`。

例如,如果用户的以前输入按下了空格键,那么返回的 Enum.UserInputType 将是 '键盘'

UserInputService.LastInputTypeChanged事件可用于跟踪用户最后使用的Enum.UserInputType更改时间。

由于 UserInputService 仅为客户端,此函数只能在 LocalScript 中使用。


返回

与用户最新输入相关的 Enum.UserInputType

代码示例

This example gets the last input type and indicates if it was keyboard input.

UserInputService:GetLastInputType

local UserInputService = game:GetService("UserInputService")
local lastInput = UserInputService:GetLastInputType()
if lastInput == Enum.UserInputType.Keyboard then
print("Most recent input was via keyboard")
end

GetMouseButtonsPressed

此函数返回一个阵列 InputObjects 与当前按下的鼠标按钮相对应的阵列。

由此函数跟踪的鼠标按钮包括:


<td>描述</td>
</tr>
</thead>
<tr>
<td>鼠标按钮1</td>
<td>左鼠标按钮。</td>
</tr>
<tr>
<td>鼠标按钮2</td>
<td>右键按钮。</td>
</tr>
<tr>
<td>鼠标按钮3</td>
<td>中间的鼠标按钮。</td>
</tr>
名称

如果用户在函数调用时没有按下任何鼠标按钮,它将返回一个空数组。

由于 UserInputService 仅为客户端,此函数只能在 LocalScript 中使用。


返回

一组与当前持有的鼠标按钮相对应的 InputObjects 阵列。

代码示例

This example checks if the user pressed MouseButton1, MouseButton2, or both mouse buttons on InputBegan().

The example can be extended to behave differently depending on which mouse buttons are pressed.

Check which MouseButtons are Pressed

local UserInputService = game:GetService("UserInputService")
-- InputBegan is a UserInputService event that fires when the player
-- begins interacting via a Human-User input device
UserInputService.InputBegan:Connect(function(_input, _gameProcessedEvent)
-- Returns an array of the pressed MouseButtons
local buttons = UserInputService:GetMouseButtonsPressed()
local m1Pressed, m2Pressed = false, false
for _, button in pairs(buttons) do
if button.UserInputType.Name == "MouseButton1" then
print("MouseButton1 is pressed")
m1Pressed = true
end
if button.UserInputType.Name == "MouseButton2" then
print("MouseButton2 is pressed")
m2Pressed = true
end
if m1Pressed and m2Pressed then
print("Both mouse buttons are pressed")
end
end
end)

GetMouseDelta

这个函数返回玩家位置的 Mouse 在最后渲染帧中的变化,以像素为单位,作为 Vector2 。此函数仅在鼠标使用 UserInputService.MouseBehavior 属性被锁定时才能工作。如果鼠标未被锁定,返回的 Vector2 值将为零。

在客户端设置和 UserInputService.MouseDeltaSensitivity 中确定的鼠标灵敏度将影响结果。

由于 UserInputService 仅为客户端,此函数只能在 LocalScript 中使用。


返回

更改鼠标的移动。

代码示例

GetMouseDelta returns the current change in movement of the mouse as a Vector2, but only if the mouse is locked. If the mouse isn't locked the values in the returned Vector2 will be zero. It measures any mouse movement in pixels from the last render step to the current render step. If the user has set their camera sensitivity to be higher or lower than 1 in the in-game menu this will affect the value returned by GetMouseDelta. The camera sensitivity is a multiplier to the amount the camera moves as a result of mouse input.

Getting Mouse Delta

local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local function OnRenderStep()
local delta = UserInputService:GetMouseDelta()
print("The mouse has moved", delta, "since the last step.")
end
RunService:BindToRenderStep("MeasureMouseMovement", Enum.RenderPriority.Input.Value, OnRenderStep)

By default, Roblox relies on a LocalScript to control the user's camera. However, this script can be overridden with a custom CameraScript. The example below demonstrates how to create a custom script to control the user's camera using many of the UserInputService events.

The script is broken into two parts:

  1. Mobile camera events, which rely on touch events
  2. Non-mobile camera events, which rely on keyboard input and tracking the user's movement

First, the camera script needs utility functions to setup the camera and set its Camera.CameraType to Scriptable so that the script can control the camera. It also needs a function to update the camera when it moves, rotates, and zooms.

Using touch events allows us to track user input as they interact with the touchscreen on their mobile device. These events allow us to handle camera movement, rotation, and zoom.

The second half of the code sample adds camera support for players on desktop devices. When input begans, the function Input() checks that the state of the input is Enum.UserInputState.Begin to ignore all keypress inputs other than when the user first presses a key down. When the user presses I and O the camera zooms in and out. When the presses down and moves their left mouse button, the script locks the player's mouse by changing the UserInputService.MouseBehavior property. The camera rotates according to the mouse's change in screen position. When the player moves their character, the camera moves with them.

All of the parts discussed above are combined and shown in the code sample below.

Create a Custom CameraScript

local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local camera = workspace.CurrentCamera
local player = Players.LocalPlayer
local character = player.CharacterAdded:Wait()
local torso = character:WaitForChild("HumanoidRootPart")
local playerPosition = torso.Position
local default_CameraPosition = torso.Position
local default_CameraRotation = Vector2.new(0, math.rad(-60))
local default_CameraZoom = 15
local cameraPosition = default_CameraPosition
local cameraRotation = default_CameraRotation
local cameraZoom = default_CameraZoom
local cameraZoomBounds = nil -- {10,200}
local cameraRotateSpeed = 10
local cameraMouseRotateSpeed = 0.25
local cameraTouchRotateSpeed = 10
local function SetCameraMode()
camera.CameraType = "Scriptable"
camera.FieldOfView = 80
camera.CameraSubject = nil
end
local function UpdateCamera()
SetCameraMode()
local cameraRotationCFrame = CFrame.Angles(0, cameraRotation.X, 0) * CFrame.Angles(cameraRotation.Y, 0, 0)
camera.CFrame = cameraRotationCFrame + cameraPosition + cameraRotationCFrame * Vector3.new(0, 0, cameraZoom)
camera.Focus = camera.CFrame - Vector3.new(0, camera.CFrame.p.Y, 0)
end
local lastTouchTranslation = nil
local function TouchMove(_touchPositions, totalTranslation, _velocity, state)
if state == Enum.UserInputState.Change or state == Enum.UserInputState.End then
local difference = totalTranslation - lastTouchTranslation
cameraPosition = cameraPosition + Vector3.new(difference.X, 0, difference.Y)
UpdateCamera()
end
lastTouchTranslation = totalTranslation
end
local lastTouchRotation = nil
local function TouchRotate(_touchPositions, rotation, _velocity, state)
if state == Enum.UserInputState.Change or state == Enum.UserInputState.End then
local difference = rotation - lastTouchRotation
cameraRotation = cameraRotation
+ Vector2.new(-difference, 0) * math.rad(cameraTouchRotateSpeed * cameraRotateSpeed)
UpdateCamera()
end
lastTouchRotation = rotation
end
local lastTouchScale = nil
local function TouchZoom(_touchPositions, scale, _velocity, state)
if state == Enum.UserInputState.Change or state == Enum.UserInputState.End then
local difference = scale - lastTouchScale
cameraZoom = cameraZoom * (1 + difference)
if cameraZoomBounds ~= nil then
cameraZoom = math.min(math.max(cameraZoom, cameraZoomBounds[1]), cameraZoomBounds[2])
else
cameraZoom = math.max(cameraZoom, 0)
end
UpdateCamera()
end
lastTouchScale = scale
end
local function Input(inputObject)
if inputObject.UserInputType == Enum.UserInputType.Keyboard then
if inputObject.UserInputState == Enum.UserInputState.Begin then
-- (I) Zoom In
if inputObject.KeyCode == Enum.KeyCode.I then
cameraZoom = cameraZoom - 15
elseif inputObject.KeyCode == Enum.KeyCode.O then
cameraZoom = cameraZoom + 15
end
-- (O) Zoom Out
if cameraZoomBounds ~= nil then
cameraZoom = math.min(math.max(cameraZoom, cameraZoomBounds[1]), cameraZoomBounds[2])
else
cameraZoom = math.max(cameraZoom, 0)
end
UpdateCamera()
end
end
local pressed = UserInputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton1)
if pressed then
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCurrentPosition
local rotation = UserInputService:GetMouseDelta()
cameraRotation = cameraRotation + rotation * math.rad(cameraMouseRotateSpeed)
else
UserInputService.MouseBehavior = Enum.MouseBehavior.Default
end
end
local function PlayerChanged()
local movement = torso.Position - playerPosition
cameraPosition = cameraPosition + movement
playerPosition = torso.Position
UpdateCamera()
end
-- Determine whether the user is on a mobile device
if UserInputService.TouchEnabled then
-- The user is on a mobile device, use Touch events
UserInputService.TouchPan:Connect(TouchMove)
UserInputService.TouchRotate:Connect(TouchRotate)
UserInputService.TouchPinch:Connect(TouchZoom)
else
-- The user is not on a mobile device use Input events
UserInputService.InputBegan:Connect(Input)
UserInputService.InputChanged:Connect(Input)
UserInputService.InputEnded:Connect(Input)
-- Camera controlled by player movement
task.wait(2)
RunService:BindToRenderStep("PlayerChanged", Enum.RenderPriority.Camera.Value - 1, PlayerChanged)
end

GetMouseLocation

此函数返回一个 Vector2 代表玩家当前屏幕位置的 Mouse 以像素表示左上角。这不会计算到 Enum.ScreenInsets ;要获得顶部左侧和底部右侧的插入,请调用 GuiService:GetGuiInset()

如果鼠标指针的位置在屏幕外或玩家的设备没有鼠标,返回的值将未确定。

由于 UserInputService 仅为客户端,此函数只能在 LocalScript 中使用。


返回

一个 Vector2 代表鼠标当前屏幕位置,以像素表示。

代码示例

This example binds the moveToMouse() to RunService's RenderStep to move the GUI to the location of the player's mouse. It does this by converting the location, a Vector2, into a UDim2.

The example sets the value of the GUI's parent ScreenGui ScreenGui.IgnoreGuiInset property to false force the GUI Inset imposed by Roblox's CoreGuis to be ignored by the ScreenGui and its descendants

In order for this example to work as expected, it should be placed in a LocalScript that is a child of the GUI being moved to the mouse's location.

Move GUI To Mouse Location

local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local gui = script.Parent
local screenGui = gui.Parent
screenGui.IgnoreGuiInset = true
local function moveGuiToMouse()
local mouseLocation = UserInputService:GetMouseLocation()
gui.Position = UDim2.fromOffset(mouseLocation.X, mouseLocation.Y)
end
moveGuiToMouse()
RunService:BindToRenderStep("moveGuiToMouse", 1, moveGuiToMouse)

GetNavigationGamepads

该函数返回连接并启用 GUI 导航的游戏手柄 UserInputTypes 阵列。这个列表是按优先级排序的,这意味着它可以被循环以确定哪个游戏手柄应具有导航控件。

连接到游戏手柄是导航游戏手柄还是仅决定哪个游戏手柄控制导航图形用户界面。这不会影响导航控件。

由于 UserInputService 仅为客户端,此函数只能在 LocalScript 中使用。

还见:


返回

一个由 UserInputTypes 组成的阵列,可用于在优先级顺序下的图形用户界面导航。

GetStringForKeyCode

获取键码字符串 返回用户应按下的键来输入给定的 Enum.KeyCode ,考虑到他们的键盘布局。对于需要按住某些修改器的键代码,该函数返回键以及修改器一起按下的键。请参阅以下示例进行进一步解释。

当使用非QWERTY键盘布局与 Roblox 交互时,键代码映射到相等的 QWERTY 位置。例如,按下 A 在 AZERTY 键盘上会导致 Enum.KeyCode.Q。这种映射可能会导致经验用户界面元素的信息不匹配。例如,“按下 M 打开地图”在 AZERTY 键盘上不准确;需要“按下 ? 打开地图”,这与 QWERTY 上的 M 位置相同。这个函数通过提供非QWERTY键盘布局使用时按下的实际键来解决这个问题。


local UserInputService = game:GetService("UserInputService")
local textLabel = script.Parent
local mapKey = Enum.KeyCode.M
textLabel.Text = "Press " .. UserInputService:GetStringForKeyCode(mapKey) .. " to open the map"
关于 QWERTY 键盘的例子

<th>返回值</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>Enum.KeyCode.Q</code></td>
<td><code>Q</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.W</code></td>
<td><code>W</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.Equals</code></td>
<td><code>=</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.At</code></td>
<td><code>2</code> 因为 <code>@</code> 是用 <kbd>Shift</kbd><kbd>2</kbd> 编写的</td>
</tr>
</tbody>
密码键码
关于 AZERTY 键盘的例子

<th>返回值</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>Enum.KeyCode.Q</code></td>
<td><code>A</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.W</code></td>
<td><code>Z</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.Equals</code></td>
<td><code>=</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.At</code></td>
<td><code>É</code></td>
</tr>
</tbody>
密码键码
游戏手柄使用

返回最近连接的游戏手柄的字符串映射。如果连接的控制器不支持,函数返回请求的键代验证码的默认字符串转换。

以下示例显示了您如何映射自定义资产到 ButtonA :


local UserInputService = game:GetService("UserInputService")
local imageLabel = script.Parent
local key = Enum.KeyCode.ButtonA
local mappings = {
ButtonA = "rbxasset://BUTTON_A_ASSET", -- Replace with the desired ButtonA asset
ButtonCross = "rbxasset://BUTTON_CROSS_ASSET" -- Replace with the desired ButtonCross asset
}
local mappedKey = UserInputService:GetStringForKeyCode(key)
local image = mappings[mappedKey]
imageLabel.Image = image
游戏手柄映射

方向键代码无论基于设备都没有任何差异。Enum.KeyCode.ButtonSelect在某些情况下有稍微不同的行为。使用两个 PlayStation 映射来确保用户看到正确的按钮。


<th>游戏机返回值</th>
<th>Xbox 返回值</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>Enum.KeyCode.ButtonA</code></td>
<td><code>按钮交叉</code></td>
<td><code>按钮A</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.ButtonB</code></td>
<td><code>按钮圆圈</code></td>
<td><code>按钮B</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.ButtonX</code></td>
<td><code>按钮方块</code></td>
<td><code>按钮X</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.ButtonY</code></td>
<td><code>按钮三角形</code></td>
<td><code>按钮Y</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.ButtonL1</code></td>
<td><code>按钮L1</code></td>
<td><code>按钮LB</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.ButtonL2</code></td>
<td><code>按钮L2</code></td>
<td><code>按钮LT</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.ButtonL3</code></td>
<td><code>按钮L3</code></td>
<td><code>按钮LS</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.ButtonR1</code></td>
<td><code>按钮R1</code></td>
<td><code>按钮RB</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.ButtonR2</code></td>
<td><code>按钮R2</code></td>
<td><code>按钮RT</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.ButtonR3</code></td>
<td><code>按钮R3</code></td>
<td><code>按钮RS</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.按钮开始</code></td>
<td><code>按钮选项</code></td>
<td><code>按钮开始</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.按钮选择</code></td>
<td><code>按钮触摸板</code> 和 <code>按钮共享</code></td>
<td><code>按钮选择</code></td>
</tr>
</tbody>
密码键码
关于键盘的系统图像

当使用 Enum.KeyCode 可能更好地用作图像时,例如用于用户界面中的 ImageLabel,您可以使用以下遗产图标。然而,建议您使用 GetImageForKeyCode() 作为更现代、跨平台方法来检索 Xbox 和 PlayStation 控制器图标。


<th>图像</th>
<th>资产 ID</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>Enum.KeyCode.ButtonX</code></td>
<td>
<img src="../../../assets/scripting/controls/xboxX.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/xboxX.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.ButtonY</code></td>
<td>
<img src="../../../assets/scripting/controls/xboxY.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/xboxY.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.ButtonA</code></td>
<td>
<img src="../../../assets/scripting/controls/xboxA.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/xboxA.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.ButtonB</code></td>
<td>
<img src="../../../assets/scripting/controls/xboxB.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/xboxB.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.DPadLeft</code></td>
<td>
<img src="../../../assets/scripting/controls/dpadLeft.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/dpadLeft.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.DPadRight</code></td>
<td>
<img src="../../../assets/scripting/controls/dpadRight.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/dpadRight.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.DPadUp</code></td>
<td>
<img src="../../../assets/scripting/controls/dpadUp.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/dpadUp.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.DPadDown</code></td>
<td>
<img src="../../../assets/scripting/controls/dpadDown.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/dpadDown.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.ButtonSelect</code></td>
<td>
<img src="../../../assets/scripting/controls/xboxView.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/xboxView.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.ButtonStart</code></td>
<td>
<img src="../../../assets/scripting/controls/xboxmenu.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/xboxmenu.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.ButtonL1</code></td>
<td>
<img src="../../../assets/scripting/controls/xboxLB.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/xboxLB.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.ButtonR1</code></td>
<td>
<img src="../../../assets/scripting/controls/xboxRB.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/xboxRB.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.ButtonL2</code></td>
<td>
<img src="../../../assets/scripting/controls/xboxLT.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/xboxLT.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.ButtonR2</code></td>
<td>
<img src="../../../assets/scripting/controls/xboxRT.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/xboxRT.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.ButtonL3</code></td>
<td>
<img src="../../../assets/scripting/controls/xboxLS.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/xboxLS.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.ButtonR3</code></td>
<td>
<img src="../../../assets/scripting/controls/xboxRS.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/xboxRS.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.Thumbstick1</code></td>
<td>
<img src="../../../assets/scripting/controls/xboxLSDirectional.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/xboxLSDirectional.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.Thumbstick2</code></td>
<td>
<img src="../../../assets/scripting/controls/xboxRSDirectional.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/xboxRSDirectional.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.Backspace</code></td>
<td>
<img src="../../../assets/scripting/controls/backspace.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/backspace.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.Return</code></td>
<td>
<img src="../../../assets/scripting/controls/return.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/return.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.左Shift</code></td>
<td>
<img src="../../../assets/scripting/controls/shift.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/shift.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.RightShift</code></td>
<td>
<img src="../../../assets/scripting/controls/shift.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/shift.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.Tab</code></td>
<td>
<img src="../../../assets/scripting/controls/tab.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/tab.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.Quote</code></td>
<td>
<img src="../../../assets/scripting/controls/apostrophe.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/apostrophe.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.Comma</code></td>
<td>
<img src="../../../assets/scripting/controls/comma.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/comma.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.Backquote</code></td>
<td>
<img src="../../../assets/scripting/controls/graveaccent.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/graveaccent.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.Period</code></td>
<td>
<img src="../../../assets/scripting/controls/period.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/period.png</code></td>
</tr>
<tr>
<td><code>Enum.KeyCode.Space</code></td>
<td>
<img src="../../../assets/scripting/controls/spacebar.png" width="24">
</img>
</td>
<td><code>rbxasset://textures/ui/Controls/spacebar.png</code></td>
</tr>
</tbody>
密码键码

参数

keyCode: Enum.KeyCode
默认值:""

返回

GetSupportedGamepadKeyCodes

此函数返回与给定 Enum.UserInputType 相关的游戏手柄支持的 KeyCodes 阵列。

这个函数可以用来确定哪些键盘被连接的游戏手柄支持,而不被支持。要确定是否支持特定的 KeyCode,请使用 UserInputService:GamepadSupports()

如果在不存在或未连接的游戏手柄上调用此函数,该函数将返回一个空数组。

由于 UserInputService 仅为客户端,此函数只能在 LocalScript 中使用。

还见:

参数

gamepadNum: Enum.UserInputType

游戏手柄的 Enum.UserInputType

默认值:""

返回

由给定游戏手柄支持的 KeyCodes 阵列。

代码示例

This example gets a list of navigation gamepads and a list of their supported Enum.KeyCodes. Then, it iterates through the supported KeyCode list and binds the ButtonX and X keys to functions if they are supported by a gamepad using the ContextActionService.

Binding Supported Gamepad KeyCodes

local UserInputService = game:GetService("UserInputService")
local ContextActionService = game:GetService("ContextActionService")
local function actionHandler(actionName, inputState, inputObject)
if inputState == Enum.UserInputState.Begin then
print("Action Handler: " .. actionName)
print(inputObject)
end
-- Since this function does not return anything, this handler will
-- "sink" the input and no other action handlers will be called after
-- this one.
end
local navGamepads = UserInputService:GetNavigationGamepads()
for _, gamepad in pairs(navGamepads) do
local supportedKeyCodes = UserInputService:GetSupportedGamepadKeyCodes(gamepad)
for _, keycode in pairs(supportedKeyCodes) do
if keycode == Enum.KeyCode.ButtonX then
ContextActionService:BindAction("SampleAction", actionHandler, false, Enum.KeyCode.ButtonX)
end
if keycode == Enum.KeyCode.X then
ContextActionService:BindAction("SampleAction", actionHandler, false, Enum.KeyCode.X)
end
end
end

IsGamepadButtonDown

这个函数检查特定按钮是否在特定游戏手柄上按下。如果 gamepad 拥有指定的 button 按下,它将返回 true;否则将返回 false。

有效的用户输入类型

指定的游戏手柄应该是以下用户输入类型枚举值之一:


<tr>
<td>Enum.UserInputType.游戏手柄1-8</td>
</tr>
名称
有效的键盘代码

指定的按钮应该是以下键盘枚值之一:


<tr>
<td>Enum.KeyCode.ButtonX</td>
</tr>
<tr>
<td>Enum.KeyCode.ButtonY</td>
</tr>
<tr>
<td>Enum.KeyCode.ButtonA</td>
</tr>
<tr>
<td>Enum.KeyCode.ButtonB</td>
</tr>
<tr>
<td>Enum.KeyCode.ButtonR1</td>
</tr>
<tr>
<td>Enum.KeyCode.ButtonL1</td>
</tr>
<tr>
<td>Enum.KeyCode.ButtonR2</td>
</tr>
<tr>
<td>Enum.KeyCode.ButtonL2</td>
</tr>
<tr>
<td>Enum.KeyCode.ButtonR3</td>
</tr>
<tr>
<td>Enum.KeyCode.ButtonL3</td>
</tr>
<tr>
<td>Enum.KeyCode.按钮开始</td>
</tr>
<tr>
<td>Enum.KeyCode.按钮选择</td>
</tr>
<tr>
<td>Enum.KeyCode.DPad左</td>
</tr>
<tr>
<td>Enum.KeyCode.DPadRight</td>
</tr>
<tr>
<td>Enum.KeyCode.DPadUp</td>
</tr>
<tr>
<td>Enum.KeyCode.DPadDown</td>
</tr>
名称

这可以用来检查是否按住了特定按钮,例如 A。例如:


local UserInputService = game:GetService("UserInputService")
local button = Enum.KeyCode.ButtonA
local gamepad = Enum.UserInputType.Gamepad1
local isButtonHeld = UserInputService:IsGamepadButtonDown(gamepad, button)

由于 UserInputService 仅为客户端,此函数只能在 LocalScript 中使用。

还见:

参数

gamepadNum: Enum.UserInputType

给定游戏手柄的 Enum.UserInputType

默认值:""
gamepadKeyCode: Enum.KeyCode

指定按钮的 Enum.KeyCode

默认值:""

返回

指定的游戏手柄按钮在指定的游戏手柄上是否按下。

代码示例

This example uses the UserInputService:IsGamepadButtonDown() function to create different behaviors when the X gamepad button is pressed than when a X button is not pressed when user input UserInputBegan|begins.

The local function IsGamepadXDown() returns whether the X gamepad button is down. This function checks if the X button is down for the activeGamepad, which is set by GetActiveGamepad. The GetActiveGamepad() fnction finds the lowest numbered navigation gamepad, connected gamepad, or gamepad1 if there are no navigation or connected gamepads.

Special Action on Gamepad Button Combo

local UserInputService = game:GetService("UserInputService")
local activeGamepad = nil
local buttonX = Enum.KeyCode.ButtonX
local function isGamepadXDown()
if activeGamepad then
return UserInputService:IsGamepadButtonDown(activeGamepad, buttonX)
end
return false
end
local function input(_input, _gameProcessedEvent)
if not isGamepadXDown() then
-- Normal event
else
-- X Button down event
end
end
local function getActiveGamepad()
local activateGamepad = nil
local navigationGamepads = {}
navigationGamepads = UserInputService:GetNavigationGamepads()
if #navigationGamepads > 1 then
for i = 1, #navigationGamepads do
if activateGamepad == nil or navigationGamepads[i].Value < activateGamepad.Value then
activateGamepad = navigationGamepads[i]
end
end
else
local connectedGamepads = {}
connectedGamepads = UserInputService:GetConnectedGamepads()
if #connectedGamepads > 0 then
for i = 1, #connectedGamepads do
if activateGamepad == nil or connectedGamepads[i].Value < activateGamepad.Value then
activateGamepad = connectedGamepads[i]
end
end
end
if activateGamepad == nil then -- nothing is connected, at least set up for gamepad1
activateGamepad = Enum.UserInputType.Gamepad1
end
end
return activateGamepad
end
if UserInputService.GamepadEnabled then
activeGamepad = getActiveGamepad()
UserInputService.InputBegan:Connect(input)
end

IsKeyDown

此函数返回用户是否按住与给定 Enum.KeyCode 相关的键。如果指定的键按下了,它将返回 true ;如果未按下,它将返回 false

这可用于检查是否按下了特定的键,例如空格键。例如:


local UserInputService = game:GetService("UserInputService")
local spaceHeld = UserInputService:IsKeyDown(Enum.KeyCode.Space)

要检索用户按下的所有键列表,请使用 UserInputService:GetKeysPressed() 函数。

由于 UserInputService 仅为客户端,此函数只能在 LocalScript 中使用。

还见:

参数

keyCode: Enum.KeyCode

键匙的 Enum.KeyCode

默认值:""

返回

是否需要按住指定的键。

代码示例

This example uses the UserInputService:IsKeyDown() function to create different behaviors when a shift key is held down than when a shift key is not held down when user input UserInputBegan|begins.

The local function IsShiftKeyDown() returns whether the left or right shift keys are pressed.

Special Action on Key Combo Press

local UserInputService = game:GetService("UserInputService")
local shiftKeyL = Enum.KeyCode.LeftShift
local shiftKeyR = Enum.KeyCode.RightShift
-- Return whether left or right shift keys are down
local function isShiftKeyDown()
return UserInputService:IsKeyDown(shiftKeyL) or UserInputService:IsKeyDown(shiftKeyR)
end
-- Handle user input began differently depending on whether a shift key is pressed
local function input(_input, _gameProcessedEvent)
if not isShiftKeyDown() then
-- Normal input
else
-- Shift input
end
end
UserInputService.InputBegan:Connect(input)

IsMouseButtonPressed

这个函数接受一个鼠标按钮 Enum.UserInputType 并返回一个 bool 指示它是否当前按下。

检查鼠标按钮的值取决于传给函数的 Enum.UserInputType 值作为参数。例如:


local UserInputService = game:GetService("UserInputService")
local pressed = UserInputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton1)

由于 UserInputService 仅为客户端,此函数只能在 LocalScript 中使用。

参数

mouseButton: Enum.UserInputType

鼠标按钮的 Enum.UserInputType

默认值:""

返回

给定的鼠标按钮是否当前已按住。

代码示例

By default, Roblox relies on a LocalScript to control the user's camera. However, this script can be overridden with a custom CameraScript. The example below demonstrates how to create a custom script to control the user's camera using many of the UserInputService events.

The script is broken into two parts:

  1. Mobile camera events, which rely on touch events
  2. Non-mobile camera events, which rely on keyboard input and tracking the user's movement

First, the camera script needs utility functions to setup the camera and set its Camera.CameraType to Scriptable so that the script can control the camera. It also needs a function to update the camera when it moves, rotates, and zooms.

Using touch events allows us to track user input as they interact with the touchscreen on their mobile device. These events allow us to handle camera movement, rotation, and zoom.

The second half of the code sample adds camera support for players on desktop devices. When input begans, the function Input() checks that the state of the input is Enum.UserInputState.Begin to ignore all keypress inputs other than when the user first presses a key down. When the user presses I and O the camera zooms in and out. When the presses down and moves their left mouse button, the script locks the player's mouse by changing the UserInputService.MouseBehavior property. The camera rotates according to the mouse's change in screen position. When the player moves their character, the camera moves with them.

All of the parts discussed above are combined and shown in the code sample below.

Create a Custom CameraScript

local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local camera = workspace.CurrentCamera
local player = Players.LocalPlayer
local character = player.CharacterAdded:Wait()
local torso = character:WaitForChild("HumanoidRootPart")
local playerPosition = torso.Position
local default_CameraPosition = torso.Position
local default_CameraRotation = Vector2.new(0, math.rad(-60))
local default_CameraZoom = 15
local cameraPosition = default_CameraPosition
local cameraRotation = default_CameraRotation
local cameraZoom = default_CameraZoom
local cameraZoomBounds = nil -- {10,200}
local cameraRotateSpeed = 10
local cameraMouseRotateSpeed = 0.25
local cameraTouchRotateSpeed = 10
local function SetCameraMode()
camera.CameraType = "Scriptable"
camera.FieldOfView = 80
camera.CameraSubject = nil
end
local function UpdateCamera()
SetCameraMode()
local cameraRotationCFrame = CFrame.Angles(0, cameraRotation.X, 0) * CFrame.Angles(cameraRotation.Y, 0, 0)
camera.CFrame = cameraRotationCFrame + cameraPosition + cameraRotationCFrame * Vector3.new(0, 0, cameraZoom)
camera.Focus = camera.CFrame - Vector3.new(0, camera.CFrame.p.Y, 0)
end
local lastTouchTranslation = nil
local function TouchMove(_touchPositions, totalTranslation, _velocity, state)
if state == Enum.UserInputState.Change or state == Enum.UserInputState.End then
local difference = totalTranslation - lastTouchTranslation
cameraPosition = cameraPosition + Vector3.new(difference.X, 0, difference.Y)
UpdateCamera()
end
lastTouchTranslation = totalTranslation
end
local lastTouchRotation = nil
local function TouchRotate(_touchPositions, rotation, _velocity, state)
if state == Enum.UserInputState.Change or state == Enum.UserInputState.End then
local difference = rotation - lastTouchRotation
cameraRotation = cameraRotation
+ Vector2.new(-difference, 0) * math.rad(cameraTouchRotateSpeed * cameraRotateSpeed)
UpdateCamera()
end
lastTouchRotation = rotation
end
local lastTouchScale = nil
local function TouchZoom(_touchPositions, scale, _velocity, state)
if state == Enum.UserInputState.Change or state == Enum.UserInputState.End then
local difference = scale - lastTouchScale
cameraZoom = cameraZoom * (1 + difference)
if cameraZoomBounds ~= nil then
cameraZoom = math.min(math.max(cameraZoom, cameraZoomBounds[1]), cameraZoomBounds[2])
else
cameraZoom = math.max(cameraZoom, 0)
end
UpdateCamera()
end
lastTouchScale = scale
end
local function Input(inputObject)
if inputObject.UserInputType == Enum.UserInputType.Keyboard then
if inputObject.UserInputState == Enum.UserInputState.Begin then
-- (I) Zoom In
if inputObject.KeyCode == Enum.KeyCode.I then
cameraZoom = cameraZoom - 15
elseif inputObject.KeyCode == Enum.KeyCode.O then
cameraZoom = cameraZoom + 15
end
-- (O) Zoom Out
if cameraZoomBounds ~= nil then
cameraZoom = math.min(math.max(cameraZoom, cameraZoomBounds[1]), cameraZoomBounds[2])
else
cameraZoom = math.max(cameraZoom, 0)
end
UpdateCamera()
end
end
local pressed = UserInputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton1)
if pressed then
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCurrentPosition
local rotation = UserInputService:GetMouseDelta()
cameraRotation = cameraRotation + rotation * math.rad(cameraMouseRotateSpeed)
else
UserInputService.MouseBehavior = Enum.MouseBehavior.Default
end
end
local function PlayerChanged()
local movement = torso.Position - playerPosition
cameraPosition = cameraPosition + movement
playerPosition = torso.Position
UpdateCamera()
end
-- Determine whether the user is on a mobile device
if UserInputService.TouchEnabled then
-- The user is on a mobile device, use Touch events
UserInputService.TouchPan:Connect(TouchMove)
UserInputService.TouchRotate:Connect(TouchRotate)
UserInputService.TouchPinch:Connect(TouchZoom)
else
-- The user is not on a mobile device use Input events
UserInputService.InputBegan:Connect(Input)
UserInputService.InputChanged:Connect(Input)
UserInputService.InputEnded:Connect(Input)
-- Camera controlled by player movement
task.wait(2)
RunService:BindToRenderStep("PlayerChanged", Enum.RenderPriority.Camera.Value - 1, PlayerChanged)
end

IsNavigationGamepad

该函数返回 true 如果指定的 Enum.UserInputType 游戏手柄允许控制导航和选择 GuiObjects

如果你想设置导航游戏手柄,你可以使用 UserInputService:SetNavigationGamepad() 。你也可以使用 UserInputService:GetNavigationGamepads() 来获取所有导航游戏手柄的列表。

例如,下面的代码检查游戏手柄1是否作为导航游戏手柄:


local UserInputService = game:GetService("UserInputService")
if UserInputService:IsNavigationGamepad(UserInputType.Gamepad1) then
print("Gamepad is a navigation gamepad!")
else
print("Gamepad is not a navigation gamepad!")
end

无论导航,所有连接的游戏手柄的列表都可以使用 `UserInput/GetConnectedGamepads 来检索。

由于 UserInputService 仅为客户端,此函数只能在 LocalScript 中使用。

还见:

参数

gamepadEnum: Enum.UserInputType

指定游戏手柄的 Enum.UserInputType

默认值:""

返回

是否指定的游戏手柄是导航游戏手柄。

RecenterUserHeadCFrame

()

此函数将 VR 头戴设备的 CFrame 重新定位到用户穿戴的头戴设备的当前方向。这意味着头戴式设备的当前方向已设置为 CFrame.new()

使用此函数将耳机 CFrame 移至播放区中央,如果它似乎处于奇怪的偏移值。

这与 VRService 函数相同,VRService:RecenterUserHeadCFrame()

由于 UserInputService 仅为客户端,此函数只能在 LocalScript 中使用。


返回

()

代码示例

This example fires the function to recenter the CFrame of the user's head to the current location of the VR headset being worn by the user.

UserInputService:RecenterUserHeadCFrame

local UserInputService = game:GetService("UserInputService")
UserInputService:RecenterUserHeadCFrame()

SetNavigationGamepad

()

SetNavigationGamepad 函数设置是否需要指定的 Enum.UserInputType 游戏手柄移动 GUI 导航器。允许移动 GUI 导航器的游戏手柄被视为 导航游戏手柄

如果 启用 参数被传递为 true,游戏手柄可以移动 GUI 导航器。如果参数是 false,游戏手柄无法移动 GUI 导航器。

如果您想检查指定的游戏手柄是否设置为导航游戏手柄,您可以使用 UserInputService:IsNavigationGamepad() 函数。您还可以使用 UserInputService:GetNavigationGamepads() 来检索所有导航游戏板的列表。

由于 UserInputService 仅为客户端,此函数只能在 LocalScript 中使用。

还见:

参数

gamepadEnum: Enum.UserInputType

指定游戏手柄的 Enum.UserInputType

默认值:""
enabled: boolean

是否指定的游戏手柄可以移动 GUI 导航器。

默认值:""

返回

()

代码示例

This example sets Gamepad1 as a navigation gamepad by passing Enum.UserInputType.Gamepad1 and true as arguments.

UserInputService:SetNavigationGamepad

local UserInputService = game:GetService("UserInputService")
UserInputService:SetNavigationGamepad(Enum.UserInputType.Gamepad1, true)

活动

DeviceAccelerationChanged

装置加速更改事件会在用户移动具有加速器的设备时发生。

加速器是一种在大多数移动设备中找到的组件,用于测量加速(速度变化)。

要确定用户的设备是否启用了加速器,请参阅UserInputService.AccelerometerEnabled

这个事件可以用来跟踪带有加速器的设备的移动。示例使用包括在移动设备加速时移动玩家角色。

此外,此事件可以与 UserInputService:GetDeviceAcceleration() 一起使用,以确定设备上的用户设备当前的移动情况,如果设备具有加速器。

该事件仅在本地发射 - 这意味着只有装置移动的玩家才能使用该事件,并且只能在 LocalScript 中工作。

参数

acceleration: InputObject

一个 InputObject ,包括 UserInputType ,以及 ** 显示每个本地设备轴上的重力力的 Position


代码示例

This example uses the accelerometer to move the player character when a mobile device is accelerated. The character will move along the axis that the device was moved.

Control Players Using the Accelerometer

local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
local SENSITIVITY = 0.2
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local ready = true
local function changeAcceleration(acceleration)
if ready then
ready = false
local accel = acceleration.Position
if accel.Y >= SENSITIVITY then
humanoid.Jump = true
end
if accel.Z <= -SENSITIVITY then
humanoid:Move(Vector3.new(-1, 0, 0))
end
if accel.Z >= SENSITIVITY then
humanoid:Move(Vector3.new(1, 0, 0))
end
if accel.X <= -SENSITIVITY then
humanoid:Move(Vector3.new(0, 0, 1))
end
if accel.X >= SENSITIVITY then
humanoid:Move(Vector3.new(0, 0, -1))
end
task.wait(1)
ready = true
end
end
UserInputService.DeviceAccelerationChanged:Connect(changeAcceleration)

DeviceGravityChanged

当设备的重力 UserInputService.DeviceGravityChanged 在具有加速器的设备上发生变化时,事件触发Vector3

设备的重力向量代表每个设备的 X、Y 和 Z 轴上的重力力。虽然重力永远不会改变,但当设备旋转并更改方向时,其对每个轴的力会发生变化。对每个轴施加的力值是从 -1 到 1 的单位向量。

加速器是一种在大多数移动设备中找到的组件,用于测量加速(速度变化)。

该事件可用于确定用户设备上的重力力的实世方向。这甚至可以用于模拟游戏中用户设备上的重力力,例如游戏内对象(见下面的示例)。

要检查用户的设备是否启用了加速器,请参阅 UserInputService.AccelerometerEnabled 。如果设备启用了加速器,你可以使用 UserInputService:GetDeviceGravity() 函数来获取用户设备上的当前重力力。

参数

gravity: InputObject

一个 InputObject ,具有 InputObject.Position 属性,显示每个本地设备轴上的重力力。这个位置可以用作确定设备相对于重力方向的方向。


代码示例

This code adds a force on a part so that it falls in the direction of actual gravity relative to the user's device.

In order for this example to work as expected, it must be placed in a LocalScript and the user's device must have an accelerometer.

Move a Ball using the Accelerometer

local Workspace = game:GetService("Workspace")
local UserInputService = game:GetService("UserInputService")
local ball = script.Parent:WaitForChild("Ball")
local mass = ball:GetMass()
local gravityForce = ball:WaitForChild("GravityForce")
local function moveBall(gravity)
gravityForce.Force = gravity.Position * Workspace.Gravity * mass
end
if UserInputService.AccelerometerEnabled then
UserInputService.DeviceGravityChanged:Connect(moveBall)
end

This example controls the player's Camera so that it matches the player's device orientation via using the device's gyroscope and accelerometer.

The camera is positioned inside the player's head, and updated to move with the player and the user's device rotation, by executing the following line every RenderStep:


camera.CFrame = CFrame.new(head.Position - Vector3.new(0,8,10)) *
currentRotation

The code sample relies on the device's gyroscope to determine when the player rotates their device. It does so by connecting to the DeviceRotationChanged() event.

The code sample relies on the device's accelerometer to retrieve the gravity vector used to determine the device's orientation (whether it is flipped upside down or not). To determine whether the device's orientation is upside down, the code sample uses the DeviceGravityChanged() event.

Since the script places the camera inside the head to create a first-person camera, the limbs are made transparent by the HideCharacter() function so that the player does not see their Player.Character when rotating the camera.

In order for this example to work as expected, it must be placed in a LocalScript and the user's device must have a gyroscope and an accelerometer.

Create a Gyroscopic Camera

local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local character = player.CharacterAdded:Wait()
local head = character:WaitForChild("Head")
local camera = workspace.CurrentCamera
local currentRotation = camera.CFrame -- CFrame.new(Vector3.new(0,0,0), Vector3.new(0,0,0))
local lastInputFrame = nil
local upsideDown = false
task.wait()
local orientationSet = false
local function GravityChanged(gravity)
if not orientationSet then
upsideDown = (gravity.Position.X < -0.5 or gravity.Position.Z > 0.5)
orientationSet = true
end
end
local function RotationChanged(_rotation, rotCFrame)
if orientationSet then
if not lastInputFrame then
lastInputFrame = rotCFrame
end
local delta = rotCFrame * lastInputFrame:inverse()
local x, y, z = delta:ToEulerAnglesXYZ()
if upsideDown then
delta = CFrame.Angles(-x, y, z)
else
delta = CFrame.Angles(x, -y, z)
end
currentRotation = currentRotation * delta
lastInputFrame = rotCFrame
end
end
local function HideCharacter()
for _, limb in pairs(character:GetChildren()) do
if limb:IsA("Part") then
limb.Transparency = 1
end
end
end
if UserInputService.GyroscopeEnabled then
UserInputService.DeviceGravityChanged:Connect(GravityChanged)
UserInputService.DeviceRotationChanged:Connect(RotationChanged)
HideCharacter()
RunService:BindToRenderStep("Camera", Enum.RenderPriority.Camera.Value, function()
camera.CFrame = CFrame.new(head.Position - Vector3.new(0, 8, 10)) * currentRotation
camera.Focus = CFrame.new(currentRotation * Vector3.new(0, 0, -10))
end)
end

DeviceRotationChanged

当用户旋转带有陀螺仪的设备时,设备旋转更改事件发生。

陀螺仪是一种在大多数移动设备中找到的组件,可检测方向和旋转速度。

事件对于跟踪设备的方向和用户旋转设备后的更改有用。要确定当前设备的旋转,您可以使用 UserInputService:GetDeviceRotation() 函数。

要检查用户的设备是否启用了陀螺仪,并且这个事件将发触发,请参阅 UserInputService.GyroscopeEnabled

此事件仅在 Roblox 客户端窗口处于焦点时发生。例如,窗口被最小化时,输入不会被捕获。

参数

rotation: InputObject

一个 InputObject 提供关于设备旋转的信息。 代表新的旋转值, 代表在某个位置值中的旋转变化, 代表在某个位置值中的旋转变化。

cframe: CFrame

一个 CFrame 代表设备当前的方向。


代码示例

This example controls the player's Camera so that it matches the player's device orientation via using the device's gyroscope and accelerometer.

The camera is positioned inside the player's head, and updated to move with the player and the user's device rotation, by executing the following line every RenderStep:


camera.CFrame = CFrame.new(head.Position - Vector3.new(0,8,10)) *
currentRotation

The code sample relies on the device's gyroscope to determine when the player rotates their device. It does so by connecting to the DeviceRotationChanged() event.

The code sample relies on the device's accelerometer to retrieve the gravity vector used to determine the device's orientation (whether it is flipped upside down or not). To determine whether the device's orientation is upside down, the code sample uses the DeviceGravityChanged() event.

Since the script places the camera inside the head to create a first-person camera, the limbs are made transparent by the HideCharacter() function so that the player does not see their Player.Character when rotating the camera.

In order for this example to work as expected, it must be placed in a LocalScript and the user's device must have a gyroscope and an accelerometer.

Create a Gyroscopic Camera

local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local character = player.CharacterAdded:Wait()
local head = character:WaitForChild("Head")
local camera = workspace.CurrentCamera
local currentRotation = camera.CFrame -- CFrame.new(Vector3.new(0,0,0), Vector3.new(0,0,0))
local lastInputFrame = nil
local upsideDown = false
task.wait()
local orientationSet = false
local function GravityChanged(gravity)
if not orientationSet then
upsideDown = (gravity.Position.X < -0.5 or gravity.Position.Z > 0.5)
orientationSet = true
end
end
local function RotationChanged(_rotation, rotCFrame)
if orientationSet then
if not lastInputFrame then
lastInputFrame = rotCFrame
end
local delta = rotCFrame * lastInputFrame:inverse()
local x, y, z = delta:ToEulerAnglesXYZ()
if upsideDown then
delta = CFrame.Angles(-x, y, z)
else
delta = CFrame.Angles(x, -y, z)
end
currentRotation = currentRotation * delta
lastInputFrame = rotCFrame
end
end
local function HideCharacter()
for _, limb in pairs(character:GetChildren()) do
if limb:IsA("Part") then
limb.Transparency = 1
end
end
end
if UserInputService.GyroscopeEnabled then
UserInputService.DeviceGravityChanged:Connect(GravityChanged)
UserInputService.DeviceRotationChanged:Connect(RotationChanged)
HideCharacter()
RunService:BindToRenderStep("Camera", Enum.RenderPriority.Camera.Value, function()
camera.CFrame = CFrame.new(head.Position - Vector3.new(0, 8, 10)) * currentRotation
camera.Focus = CFrame.new(currentRotation * Vector3.new(0, 0, -10))
end)
end

This code adds a force on a part so that it falls in the direction of actual gravity relative to the user's device.

In order for this example to work as expected, it must be placed in a LocalScript and the user's device must have an accelerometer.

Move a Ball using the Accelerometer

local Workspace = game:GetService("Workspace")
local UserInputService = game:GetService("UserInputService")
local ball = script.Parent:WaitForChild("Ball")
local mass = ball:GetMass()
local gravityForce = ball:WaitForChild("GravityForce")
local function moveBall(gravity)
gravityForce.Force = gravity.Position * Workspace.Gravity * mass
end
if UserInputService.AccelerometerEnabled then
UserInputService.DeviceGravityChanged:Connect(moveBall)
end

GamepadConnected

游戏手柄连接事件会在游戏手柄连接到客户端时触发。

由于 Roblox 游戏支持多个控制器,这个事件在与 UserInputService.GamepadDisconnected 事件匹配时跟踪哪些控制器/游戏板是激活的时有用。您还可以使用 UserInputService:GetConnectedGamepads() 来找到正确的游戏手柄进行使用。

以下示例显示了游戏手柄连接到客户端时的跟踪使用示例。


local UserInputService = game:GetService("UserInputService")
local function GamepadConnected(gamepad)
print("Player has plugged controller: " .. tostring(gamepad))
end)
UserInputService.GamepadConnected:Connect(GamepadConnected)

如果您想查看哪些设备已连接,您可以使用 UserInputService:GetConnectedGamepads() 函数。

由于此事件是在本地发射的,它只能在 LocalScript 中使用。

还见:

参数

gamepadNum: Enum.UserInputType

连接的游戏手柄的 Enum.UserInputType


GamepadDisconnected

游戏手柄断开事件会在游戏手柄断开时发生。

由于 Roblox 游戏支持多个控制器,这个事件在与 UserInputService.GamepadConnected 事件匹配时跟踪哪些控制器/游戏板是激活的时有用。您还可以使用 UserInputService:GetConnectedGamepads() 来找到正确的游戏手柄进行使用。

以下示例显示了游戏手柄从客户端断开时的跟踪使用示例。


local UserInputService = game:GetService("UserInputService")
local function GamepadDisconnected(gamepad)
print("Player has unplugged controller: " .. tostring(gamepad))
end)
UserInputService.GamepadDisconnected:Connect(GamepadDisconnected)

由于此事件是在本地发射的,它只能在 LocalScript 中使用。

还见:

参数

gamepadNum: Enum.UserInputType

断开游戏手柄的 Enum.UserInputType


InputBegan

输入开始事件在用户开始通过人机界面设备(鼠标向下、触摸开始、键盘按钮向下等)进行交互时触发。

它可以用于跟踪用户互动的开始,例如当用户第一次与图形用户界面元素、游戏手柄等互动时。它不捕获鼠标轮移动。

这个事件可以与 UserInputService.InputChangedUserInputService.InputEnded 一起使用,来跟踪用户输入、更改和结束的时间。

此事件仅在 Roblox 客户端窗口处于焦点时发生。例如,窗口被最小化时,输入不会被捕获。

由于此事件仅在本地发射,它只能在 LocalScript 中使用。

参数

包含用户输入信息的 InputObject 实例。

gameProcessedEvent: boolean

指示游戏引擎是否内部观察到此输入并采取行动。一般来说,这指的是 UI 处理,因此如果从这个输入触摸或单击了按钮,那么 gameProcessedEvent 将是 true。这也适用于通过 ContextActionService 连接的输入事件。


代码示例

The following example demonstrates one of many usage examples of handling user input from InputBegan depending on its type.

Handling InputBegan

-- In order to use the InputBegan event, the UserInputService service must be used
local UserInputService = game:GetService("UserInputService")
-- A sample function providing multiple usage cases for various types of user input
UserInputService.InputBegan:Connect(function(input, gameProcessed)
if input.UserInputType == Enum.UserInputType.Keyboard then
print("A key is being pushed down! Key:", input.KeyCode)
elseif input.UserInputType == Enum.UserInputType.MouseButton1 then
print("The left mouse button has been pressed down at", input.Position)
elseif input.UserInputType == Enum.UserInputType.MouseButton2 then
print("The right mouse button has been pressed down at", input.Position)
elseif input.UserInputType == Enum.UserInputType.Touch then
print("A touchscreen input has started at", input.Position)
elseif input.UserInputType == Enum.UserInputType.Gamepad1 then
print("A button is being pressed on a gamepad! Button:", input.KeyCode)
end
if gameProcessed then
print("The game engine internally observed this input!")
else
print("The game engine did not internally observe this input!")
end
end)

InputChanged

当用户通过人机界面设备(鼠标按钮向下、触摸开始、键盘按钮向下等)更改他们的互动方式时,输入更改事件会触发(例如)。

要忽略 Roblox 自动处理的事件,例如在 ScrollingFrame 中滚动,检查 gameProcessedEvent 参数为 false。这个事件可以与 UserInputService.InputBeganUserInputService.InputEnded 一起使用,来跟踪用户输入、更改和结束的时间。

此事件仅在 Roblox 客户端窗口处于焦点时发生。例如,窗口被最小化时,输入不会被捕获。

由于此事件仅在本地发射,它只能在 LocalScript 中使用。

参数

包含用户输入信息的 InputObject 实例。

gameProcessedEvent: boolean

指示游戏引擎是否内部观察到此输入并采取行动。一般来说,这指的是 UI 处理,因此如果从这个输入触摸或单击了按钮,那么 gameProcessedEvent 将是 true。这也适用于通过 ContextActionService 连接的输入事件。


代码示例

The following example demonstrates one of many usage examples of handling user input from InputChanged depending on its type.

Handling InputChanged

-- In order to use the InputChanged event, the UserInputService service must be used
local UserInputService = game:GetService("UserInputService")
-- Prints the current input position and the change (delta) in position
local function printMovement(input)
print("Position:", input.Position)
print("Movement Delta:", input.Delta)
end
-- A sample function providing multiple usage cases for various types of user input
local function InputChanged(input, _gameProcessed)
if input.UserInputType == Enum.UserInputType.MouseMovement then
print("The mouse has been moved!")
printMovement(input)
elseif input.UserInputType == Enum.UserInputType.MouseWheel then
print("The mouse wheel has been scrolled!")
print("Wheel Movement:", input.Position.Z)
elseif input.UserInputType == Enum.UserInputType.Gamepad1 then
if input.KeyCode == Enum.KeyCode.Thumbstick1 then
print("The left thumbstick has been moved!")
printMovement(input)
elseif input.KeyCode == Enum.KeyCode.Thumbstick2 then
print("The right thumbstick has been moved!")
printMovement(input)
elseif input.KeyCode == Enum.KeyCode.ButtonL2 then
print("The pressure being applied to the left trigger has changed!")
print("Pressure:", input.Position.Z)
elseif input.KeyCode == Enum.KeyCode.ButtonR2 then
print("The pressure being applied to the right trigger has changed!")
print("Pressure:", input.Position.Z)
end
elseif input.UserInputType == Enum.UserInputType.Touch then
print("The user's finger is moving on the screen!")
printMovement(input)
elseif input.UserInputType == Enum.UserInputType.Gyro then
local _rotInput, rotCFrame = UserInputService:GetDeviceRotation()
local rotX, rotY, rotZ = rotCFrame:toEulerAnglesXYZ()
local rot = Vector3.new(math.deg(rotX), math.deg(rotY), math.deg(rotZ))
print("The rotation of the user's mobile device has been changed!")
print("Position", rotCFrame.p)
print("Rotation:", rot)
elseif input.UserInputType == Enum.UserInputType.Accelerometer then
print("The acceleration of the user's mobile device has been changed!")
printMovement(input)
end
end
UserInputService.InputChanged:Connect(InputChanged)

InputEnded

输入已结束事件会在用户停止通过人机界面设备(鼠标向下、触摸开始、键盘按钮向下等)进行交互时触发。当跟踪用户释放键盘键、鼠标按钮、触摸屏输入等时,这很有用

这个事件可以与 UserInputService.InputBeganUserInputService.InputChanged 一起使用,来跟踪用户输入、更改和结束的时间。

此事件仅在 Roblox 客户端窗口处于焦点时发生。例如,窗口被最小化时,输入不会被捕获。

由于此事件仅在本地发射,它只能在 LocalScript 中使用。

参数

一个 InputObject 实例,包含关于用户输入的信息。

gameProcessedEvent: boolean

指示游戏引擎是否内部观察到此输入并采取行动。一般来说,这指的是 UI 处理,因此如果从这个输入触摸或单击了按钮,那么 gameProcessedEvent 将是 true。这也适用于通过 ContextActionService 连接的输入事件。


代码示例

The following example demonstrates one of many usage examples of handling user input from InputEnded depending on its type.

Handling InputEnded

-- In order to use the InputChanged event, the UserInputService service must be used
local UserInputService = game:GetService("UserInputService")
-- A sample function providing multiple usage cases for various types of user input
UserInputService.InputEnded:Connect(function(input, gameProcessed)
if input.UserInputType == Enum.UserInputType.Keyboard then
print("A key has been released! Key:", input.KeyCode)
elseif input.UserInputType == Enum.UserInputType.MouseButton1 then
print("The left mouse button has been released at", input.Position)
elseif input.UserInputType == Enum.UserInputType.MouseButton2 then
print("The right mouse button has been released at", input.Position)
elseif input.UserInputType == Enum.UserInputType.Touch then
print("A touchscreen input has been released at", input.Position)
elseif input.UserInputType == Enum.UserInputType.Gamepad1 then
print("A button has been released on a gamepad! Button:", input.KeyCode)
end
if gameProcessed then
print("The game engine internally observed this input!")
else
print("The game engine did not internally observe this input!")
end
end)

JumpRequest

当客户端发出跳转请求时,UserInputService 跳转请求事件会发生,例如当客户端按下空格键或跳跃按钮时,在移动设备上。

该事件会在用户尝试将其 Player.Character 跳跃时触发。默认行为会回应跳跃请求,设置玩家的 Humanoid.Jump 属性为真值,使玩家的角色跳跃。

事件可用于跟踪玩家每次想跳跃的时间。而不是使用它来让玩家跳跃,这应该用于更改默认跳跃行为 - 例如禁用跳跃。

例如,下面的代码每次玩家发送跳跃请求时都会打印“跳跃”。


local UserInputService = game:GetService("UserInputService")
function onJumpRequest()
print("Jump!")
end
UserInputService.JumpRequest:Connect(onJumpRequest)

由于此事件为单次跳跃请求触发多次,建议使用 缓冲

如果您想将键或按钮连接到其他操作,请考虑使用事件,例如 UserInputService:GetKeysPressed()UserInputService.InputBeganContextActionService

由于此事件仅在本地发射,它只能在 LocalScript 中使用。


代码示例

This code sample disables jumping for the LocalPlayer by setting the Enum.HumanoidStateType.Jumping state to false. Setting this state to false as soon as the user tries to jump cancels the jump.

In order for this example to work as expected, it should be placed in a LocalScript.

Disable Jumping

local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
-- Fires when the user tries to jump
local function jump()
humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping, false)
end
UserInputService.JumpRequest:Connect(jump)

LastInputTypeChanged

客户端通过人机界面设备改变互动方式时,UserInputService.LastInputTypeChanged将随时发生。(i.e.从 MouseMovement 到 MouseWheel 或从 Thumbstick1 到 Thumbstick2)。

无论输入类型最后是否发生了变化,您都可以使用 UserInputService:GetLastInputType() 函数来获取最后一个输入类型的值。

由于此事件仅在本地发射,它只能在 LocalScript 中使用。

参数

lastInputType: Enum.UserInputType

一个 Enum.UserInputType 指示最后一个输入类型。


代码示例

This example hides the mouse icon while the player beings using their keyboard, such as to chat or enter text into a TextBox. The mouse icon reappears when the user resumes mouse input.

This uses the LastInputType() event to determine when the user begins keyboard input and mouse input - based on the value of the lastInputType argument.

In order for this example to work as expected, it should be placed in a LocalScript.

Hide Mouse During Keyboard Input

local UserInputService = game:GetService("UserInputService")
local mouseInput = {
Enum.UserInputType.MouseButton1,
Enum.UserInputType.MouseButton2,
Enum.UserInputType.MouseButton3,
Enum.UserInputType.MouseMovement,
Enum.UserInputType.MouseWheel,
}
local keyboard = Enum.UserInputType.Keyboard
local function toggleMouse(lastInputType)
if lastInputType == keyboard then
UserInputService.MouseIconEnabled = false
return
end
for _, mouse in pairs(mouseInput) do
if lastInputType == mouse then
UserInputService.MouseIconEnabled = true
return
end
end
end
UserInputService.LastInputTypeChanged:Connect(toggleMouse)

PointerAction

指针操作 在用户执行特定的指针操动作时发生。例如滚动鼠标轮。

参数

wheel: number
pan: Vector2
pinch: number
gameProcessedEvent: boolean

TextBoxFocusReleased

当客户端失去对 的焦点时,事件会触发,通常是当客户端按下返回键或单击/触摸屏幕上的其他地方停止输入文本时。

例如,下面的代码打印了事件触发时丢失焦点的名称 TextBox


local UserInputService = game:GetService("UserInputService")
function TextBoxFocusReleased(textbox)
print(textbox.Name)
end
UserInputService.TextBoxFocusReleased:Connect(TextBoxFocusReleased)

它可以与 UserInputService.TextBoxFocused 一起使用,以跟踪当一个 TextBox 获得和失去焦点时。

由于此事件仅在本地发射,它只能在 LocalScript 中使用。

还看到也看到

参数

textboxReleased: TextBox

那个 TextBox 失去了焦点。


TextBoxFocused

当一个获得焦点在 TextBox 上时,此事件会触发,通常是当客户单击/点击文本框以开始输入文本时。这也会在使用 TextBox:CaptureFocus() 将文本框焦点聚焦时发射。

例如,下面的代码打印了事件触发时聚焦的 TextBox 名称。


local UserInputService = game:GetService("UserInputService")
function TextBoxFocused(textbox)
print(textbox.Name)
end)
UserInputService.TextBoxFocused:Connect(TextBoxFocused)

它可以与 UserInputService.FocusReleased 一起使用,追踪文本框是否获得或失去焦点。

由于此事件仅在本地发射,它只能在 LocalScript 中使用。

还看到也看到

参数

textboxFocused: TextBox

获得焦点的 TextBox


TouchDrag

参数

dragDirection: Enum.SwipeDirection
numberOfTouches: number
gameProcessedEvent: boolean

TouchEnded

当用户从触摸启用的设备的屏幕上释放手指时,触摸结束事件发生,结束对设备的触摸输入。

该事件可用于确定用户何时停止触摸其设备的屏幕。它可以与 UserInputService.TouchStarted 匹配,以确定用户何时开始和停止触摸屏幕。

例如,下面的代码打印了用户停止触摸屏幕的屏幕位置。


local UserInputService = game:GetService("UserInputService")
function TouchEnded(touch, gameProcessedEvent)
print("Touch ended at " .. tostring(touch.Position))
end
UserInputService.TouchEnded:Connect(TouchEnded)

触摸输入对象在触摸期间始终是相同的输入对象。因此,当触摸对象时比较 InputObjects 是有效的,以确定它是否是同一只手指。

要检查用户的设备是否启用触摸,并且触摸事件会触发,请参阅 UserInputService.TouchEnabled

此事件仅在 Roblox 客户端窗口处于焦点时发生。例如,窗口被最小化时,输入不会被捕获。

由于此事件仅在本地发射,它只能在 LocalScript 中使用。

还见:

参数

包含用户输入信息的 InputObject 实例。

gameProcessedEvent: boolean

指示游戏引擎是否内部观察到此输入并采取行动。一般来说,这指的是 UI 处理,因此如果从这个输入触摸或单击了按钮,那么 gameProcessedEvent 将是 true。这也适用于通过 ContextActionService 连接的输入事件。


代码示例

The code sample below demonstrates the difference between a TouchTap() and TouchLongPress() by creating a GuiObject|GUI Frame that appears when user touches the screen of their device and disappears when the Class.UserInputEvent.TouchEnded|touch ends. When the long press event fires, the GUI doubles in size. Also, the GUI moves to stay centered under the user's finger when the player moves their finger.

In order for the TouchLongPress() to fire, the user touch the screen and hold their finger still for a short period of time. Once the touch moves, the long press event will not fire.

In order for the example to work as expected, it should be placed in a LocalScript that is parented to a ScreenGui.

The Difference Between TouchTap and TouchLongPress

local UserInputService = game:GetService("UserInputService")
-- The parent of this script (a ScreenGui)
local touchScreenGui = script.Parent
-- Create the GUI frame that the user interacts with through Touch
-- events
local touchGui = Instance.new("Frame")
touchGui.Name = "TouchGui"
touchGui.AnchorPoint = Vector2.new(0.5, 0.5)
-- Fires when the touches their device's screen
local function TouchTap(touchPositions, _gameProcessedEvent)
touchGui.Parent = touchScreenGui
touchGui.Position = UDim2.new(0, touchPositions[1].X, 0, touchPositions[1].Y)
touchGui.Size = UDim2.new(0, 50, 0, 50)
end
-- Fires when a user starts touching their device's screen and does not
-- move their finger for a short period of time
local function TouchLong(_touchPositions, _state, _gameProcessedEvent)
touchGui.Size = UDim2.new(0, 100, 0, 100)
end
-- Fires when the user moves their finger while touching their device's
-- screen
local function TouchMove(touch, _gameProcessedEvent)
touchGui.Position = UDim2.new(0, touch.Position.X, 0, touch.Position.Y)
end
-- Fires when the user stops touching their device's screen
local function TouchEnd(_touch, _gameProcessedEvent)
touchGui.Parent = nil
touchGui.Size = UDim2.new(0, 50, 0, 50)
end
-- Only use the Touch events if the user is on a mobile device
if UserInputService.TouchEnabled then
UserInputService.TouchTap:Connect(TouchTap)
UserInputService.TouchLongPress:Connect(TouchLong)
UserInputService.TouchMoved:Connect(TouchMove)
UserInputService.TouchEnded:Connect(TouchEnd)
end

TouchLongPress

当用户在触摸启用的设备的相同屏幕位置上按住至少一个手指一小段时间时,发射。

这个事件可以用来确定用户何时按住手指在游戏中GuiObject或元素上。

下面的例子打印用户在同一屏幕位置按住至少一个手指的短时间后的长按state。可能的状态包括:开始更改结束取消


local UserInputService = game:GetService("UserInputService")
function TouchLongPress(TouchPositions, state, gameProcessedEvent)
print("Long press event fired. State of press: " .. tostring(state))
end
UserInputService.TouchLongPress:Connect(TouchLongPress)

要检查用户的设备是否启用触摸,以及触摸事件是否会触发,请参阅UserInputService.TouchEnabled

它可以与 UserInputService.TouchStartedUserInputService.TouchEnded 匹配,以确定用户何时开始和停止触摸屏幕。

此事件仅在 Roblox 客户端窗口处于焦点时发生。例如,窗口被最小化时,输入不会被捕获。

由于此事件仅在本地发射,它只能在 LocalScript 中使用。

还见:

参数

touchPositions: Array

一个由 Vector2 个对象组成的阵列,表示参与手势的手指位置。

gameProcessedEvent: boolean

指示游戏引擎是否内部观察到此输入并采取行动。一般来说,这指的是 UI 处理,因此如果从这个输入触摸或单击了按钮,那么 gameProcessedEvent 将是 true。这也适用于通过 ContextActionService 连接的输入事件。


代码示例

The code sample below demonstrates the difference between a TouchTap() and TouchLongPress() by creating a GuiObject|GUI Frame that appears when user touches the screen of their device and disappears when the Class.UserInputEvent.TouchEnded|touch ends. When the long press event fires, the GUI doubles in size. Also, the GUI moves to stay centered under the user's finger when the player moves their finger.

In order for the TouchLongPress() to fire, the user touch the screen and hold their finger still for a short period of time. Once the touch moves, the long press event will not fire.

In order for the example to work as expected, it should be placed in a LocalScript that is parented to a ScreenGui.

The Difference Between TouchTap and TouchLongPress

local UserInputService = game:GetService("UserInputService")
-- The parent of this script (a ScreenGui)
local touchScreenGui = script.Parent
-- Create the GUI frame that the user interacts with through Touch
-- events
local touchGui = Instance.new("Frame")
touchGui.Name = "TouchGui"
touchGui.AnchorPoint = Vector2.new(0.5, 0.5)
-- Fires when the touches their device's screen
local function TouchTap(touchPositions, _gameProcessedEvent)
touchGui.Parent = touchScreenGui
touchGui.Position = UDim2.new(0, touchPositions[1].X, 0, touchPositions[1].Y)
touchGui.Size = UDim2.new(0, 50, 0, 50)
end
-- Fires when a user starts touching their device's screen and does not
-- move their finger for a short period of time
local function TouchLong(_touchPositions, _state, _gameProcessedEvent)
touchGui.Size = UDim2.new(0, 100, 0, 100)
end
-- Fires when the user moves their finger while touching their device's
-- screen
local function TouchMove(touch, _gameProcessedEvent)
touchGui.Position = UDim2.new(0, touch.Position.X, 0, touch.Position.Y)
end
-- Fires when the user stops touching their device's screen
local function TouchEnd(_touch, _gameProcessedEvent)
touchGui.Parent = nil
touchGui.Size = UDim2.new(0, 50, 0, 50)
end
-- Only use the Touch events if the user is on a mobile device
if UserInputService.TouchEnabled then
UserInputService.TouchTap:Connect(TouchTap)
UserInputService.TouchLongPress:Connect(TouchLong)
UserInputService.TouchMoved:Connect(TouchMove)
UserInputService.TouchEnded:Connect(TouchEnd)
end

TouchMoved

当用户在 TouchEnabled 设备上移动手指时发生火焰,例如平板电脑或智能手机。

这个事件对于跟踪用户是否在屏幕上移动手指以及用户移动手指的位置有用。

下面的代码显示了触摸从其前一个位置移动到 TouchEnabled 设备上的新位置。请注意,传递的 InputObject.Position 参数上的 touch 是一个 Vector3 ,但仅包含 X 和 Y 坐标;Z 总是 0。


local UserInputService = game:GetService("UserInputService")
function onTouchMoved(touch, gameProcessedEvent)
local oldPosition = touch.Position - touch.Delta
print("Touch moved from " .. tostring(oldPosition) .. " to " .. tostring(touch.Position))
end
UserInputService.TouchMoved:Connect(onTouchMoved)

将此事件与 UserInputService.TouchStartedUserInputService.TouchEnded 匹配,以确定用户何时开始触摸屏幕、移动手指时触摸屏幕以及何时停止触摸屏幕。

要检查用户的设备是否支持触摸以及触摸事件是否会触发,请参阅 UserInputService.TouchEnabled

此事件仅在 Roblox 客户端窗口处于焦点时发生。例如,窗口被最小化时,输入不会被捕获。

由于此事件仅在本地发射,它只能在 LocalScript 中使用。

还见:

参数

包含用户输入信息的 InputObject 实例。

gameProcessedEvent: boolean

指示游戏引擎是否内部观察到此输入并采取行动。一般来说,这指的是 UI 处理,因此如果从这个输入触摸或单击了按钮,那么 gameProcessedEvent 将是 true。这也适用于通过 ContextActionService 连接的输入事件。


代码示例

The code sample below demonstrates the difference between a TouchTap() and TouchLongPress() by creating a GuiObject|GUI Frame that appears when user touches the screen of their device and disappears when the Class.UserInputEvent.TouchEnded|touch ends. When the long press event fires, the GUI doubles in size. Also, the GUI moves to stay centered under the user's finger when the player moves their finger.

In order for the TouchLongPress() to fire, the user touch the screen and hold their finger still for a short period of time. Once the touch moves, the long press event will not fire.

In order for the example to work as expected, it should be placed in a LocalScript that is parented to a ScreenGui.

The Difference Between TouchTap and TouchLongPress

local UserInputService = game:GetService("UserInputService")
-- The parent of this script (a ScreenGui)
local touchScreenGui = script.Parent
-- Create the GUI frame that the user interacts with through Touch
-- events
local touchGui = Instance.new("Frame")
touchGui.Name = "TouchGui"
touchGui.AnchorPoint = Vector2.new(0.5, 0.5)
-- Fires when the touches their device's screen
local function TouchTap(touchPositions, _gameProcessedEvent)
touchGui.Parent = touchScreenGui
touchGui.Position = UDim2.new(0, touchPositions[1].X, 0, touchPositions[1].Y)
touchGui.Size = UDim2.new(0, 50, 0, 50)
end
-- Fires when a user starts touching their device's screen and does not
-- move their finger for a short period of time
local function TouchLong(_touchPositions, _state, _gameProcessedEvent)
touchGui.Size = UDim2.new(0, 100, 0, 100)
end
-- Fires when the user moves their finger while touching their device's
-- screen
local function TouchMove(touch, _gameProcessedEvent)
touchGui.Position = UDim2.new(0, touch.Position.X, 0, touch.Position.Y)
end
-- Fires when the user stops touching their device's screen
local function TouchEnd(_touch, _gameProcessedEvent)
touchGui.Parent = nil
touchGui.Size = UDim2.new(0, 50, 0, 50)
end
-- Only use the Touch events if the user is on a mobile device
if UserInputService.TouchEnabled then
UserInputService.TouchTap:Connect(TouchTap)
UserInputService.TouchLongPress:Connect(TouchLong)
UserInputService.TouchMoved:Connect(TouchMove)
UserInputService.TouchEnded:Connect(TouchEnd)
end

TouchPan

触摸板事件在用户拖动至少一个手指到 TouchEnabled 设备时触发。

此事件可用于确定用户何时在触摸启用的设备的屏幕上移动手指 - 例如,在自定义相机脚本中旋转 Camera

下面的代码打印“触摸拖动速度”,随后是用户拖动手指时屏幕上的速度。


local UserInputService = game:GetService("UserInputService")
UserInputService.TouchPan:Connect(function(touchPositions, totalTranslation, velocity, state, gameProcessedEvent)
print("Speed of touch drag: " .. tostring(velocity))
end)

看看另一个有用的 UserInputService 函数在这里 UserInputService.TouchRotate .

此事件仅在 Roblox 客户端窗口处于焦点时发生。例如,窗口被最小化时,输入不会被捕获。

由于此事件仅在本地发射,它只能在 LocalScript 中使用。

还见:

参数

touchPositions: Array

一个由 Vector2 个对象组成的阵列,表示参与手势的触摸位置(例如手指)。

totalTranslation: Vector2

从开始到结束的平底锅动作的尺寸(以像素计)。

velocity: Vector2

平底锅的手势速度(以像素计)每秒钟。

gameProcessedEvent: boolean

指示游戏引擎是否内部观察到此输入并采取行动。一般来说,这指的是 UI 处理,因此如果从这个输入触摸或单击了按钮,那么 gameProcessedEvent 将是 true。这也适用于通过 ContextActionService 连接的输入事件。


代码示例

By default, Roblox relies on a LocalScript to control the user's camera. However, this script can be overridden with a custom CameraScript. The example below demonstrates how to create a custom script to control the user's camera using many of the UserInputService events.

The script is broken into two parts:

  1. Mobile camera events, which rely on touch events
  2. Non-mobile camera events, which rely on keyboard input and tracking the user's movement

First, the camera script needs utility functions to setup the camera and set its Camera.CameraType to Scriptable so that the script can control the camera. It also needs a function to update the camera when it moves, rotates, and zooms.

Using touch events allows us to track user input as they interact with the touchscreen on their mobile device. These events allow us to handle camera movement, rotation, and zoom.

The second half of the code sample adds camera support for players on desktop devices. When input begans, the function Input() checks that the state of the input is Enum.UserInputState.Begin to ignore all keypress inputs other than when the user first presses a key down. When the user presses I and O the camera zooms in and out. When the presses down and moves their left mouse button, the script locks the player's mouse by changing the UserInputService.MouseBehavior property. The camera rotates according to the mouse's change in screen position. When the player moves their character, the camera moves with them.

All of the parts discussed above are combined and shown in the code sample below.

Create a Custom CameraScript

local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local camera = workspace.CurrentCamera
local player = Players.LocalPlayer
local character = player.CharacterAdded:Wait()
local torso = character:WaitForChild("HumanoidRootPart")
local playerPosition = torso.Position
local default_CameraPosition = torso.Position
local default_CameraRotation = Vector2.new(0, math.rad(-60))
local default_CameraZoom = 15
local cameraPosition = default_CameraPosition
local cameraRotation = default_CameraRotation
local cameraZoom = default_CameraZoom
local cameraZoomBounds = nil -- {10,200}
local cameraRotateSpeed = 10
local cameraMouseRotateSpeed = 0.25
local cameraTouchRotateSpeed = 10
local function SetCameraMode()
camera.CameraType = "Scriptable"
camera.FieldOfView = 80
camera.CameraSubject = nil
end
local function UpdateCamera()
SetCameraMode()
local cameraRotationCFrame = CFrame.Angles(0, cameraRotation.X, 0) * CFrame.Angles(cameraRotation.Y, 0, 0)
camera.CFrame = cameraRotationCFrame + cameraPosition + cameraRotationCFrame * Vector3.new(0, 0, cameraZoom)
camera.Focus = camera.CFrame - Vector3.new(0, camera.CFrame.p.Y, 0)
end
local lastTouchTranslation = nil
local function TouchMove(_touchPositions, totalTranslation, _velocity, state)
if state == Enum.UserInputState.Change or state == Enum.UserInputState.End then
local difference = totalTranslation - lastTouchTranslation
cameraPosition = cameraPosition + Vector3.new(difference.X, 0, difference.Y)
UpdateCamera()
end
lastTouchTranslation = totalTranslation
end
local lastTouchRotation = nil
local function TouchRotate(_touchPositions, rotation, _velocity, state)
if state == Enum.UserInputState.Change or state == Enum.UserInputState.End then
local difference = rotation - lastTouchRotation
cameraRotation = cameraRotation
+ Vector2.new(-difference, 0) * math.rad(cameraTouchRotateSpeed * cameraRotateSpeed)
UpdateCamera()
end
lastTouchRotation = rotation
end
local lastTouchScale = nil
local function TouchZoom(_touchPositions, scale, _velocity, state)
if state == Enum.UserInputState.Change or state == Enum.UserInputState.End then
local difference = scale - lastTouchScale
cameraZoom = cameraZoom * (1 + difference)
if cameraZoomBounds ~= nil then
cameraZoom = math.min(math.max(cameraZoom, cameraZoomBounds[1]), cameraZoomBounds[2])
else
cameraZoom = math.max(cameraZoom, 0)
end
UpdateCamera()
end
lastTouchScale = scale
end
local function Input(inputObject)
if inputObject.UserInputType == Enum.UserInputType.Keyboard then
if inputObject.UserInputState == Enum.UserInputState.Begin then
-- (I) Zoom In
if inputObject.KeyCode == Enum.KeyCode.I then
cameraZoom = cameraZoom - 15
elseif inputObject.KeyCode == Enum.KeyCode.O then
cameraZoom = cameraZoom + 15
end
-- (O) Zoom Out
if cameraZoomBounds ~= nil then
cameraZoom = math.min(math.max(cameraZoom, cameraZoomBounds[1]), cameraZoomBounds[2])
else
cameraZoom = math.max(cameraZoom, 0)
end
UpdateCamera()
end
end
local pressed = UserInputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton1)
if pressed then
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCurrentPosition
local rotation = UserInputService:GetMouseDelta()
cameraRotation = cameraRotation + rotation * math.rad(cameraMouseRotateSpeed)
else
UserInputService.MouseBehavior = Enum.MouseBehavior.Default
end
end
local function PlayerChanged()
local movement = torso.Position - playerPosition
cameraPosition = cameraPosition + movement
playerPosition = torso.Position
UpdateCamera()
end
-- Determine whether the user is on a mobile device
if UserInputService.TouchEnabled then
-- The user is on a mobile device, use Touch events
UserInputService.TouchPan:Connect(TouchMove)
UserInputService.TouchRotate:Connect(TouchRotate)
UserInputService.TouchPinch:Connect(TouchZoom)
else
-- The user is not on a mobile device use Input events
UserInputService.InputBegan:Connect(Input)
UserInputService.InputChanged:Connect(Input)
UserInputService.InputEnded:Connect(Input)
-- Camera controlled by player movement
task.wait(2)
RunService:BindToRenderStep("PlayerChanged", Enum.RenderPriority.Camera.Value - 1, PlayerChanged)
end

TouchPinch

当用户放置并移动两个手指到 TouchEnabled 设备的屏幕时,发射。

例实例,下面的代码打印了自从触摸捏动开始以来相机缩放比例的变化量。


local UserInputService = game:GetService("UserInputService")
UserInputService.TouchPinch:Connect(function(touchPositions, scale, velocity, state, gameProcessedEvent)
print("Scale difference since beginning of pinch: " .. tostring(scale))
end)

要检查用户的设备是否启用触摸,并且触摸事件会触发,请参阅 UserInputService.TouchEnabled

此事件仅在 Roblox 客户端窗口处于焦点时发生。例如,窗口最小化时,输入不会被捕获。由于此事件仅在本地发射,它只能在 LocalScript 中使用。

还见:

参数

touchPositions: Array

一个 Vector2s 阵列,表示涉及握住手势的手指的屏幕位置,以像素为单位。

scale: number

从开始到完成的握住力(以像素计)除以开始握住位置。

velocity: number

按钮手势的速度(以像素计)每秒钟。

gameProcessedEvent: boolean

指示游戏引擎是否内部观察到此输入并采取行动。一般来说,这指的是 UI 处理,因此如果从这个输入触摸或单击了按钮,那么 gameProcessedEvent 将是 true。这也适用于通过 ContextActionService 连接的输入事件。


代码示例

By default, Roblox relies on a LocalScript to control the user's camera. However, this script can be overridden with a custom CameraScript. The example below demonstrates how to create a custom script to control the user's camera using many of the UserInputService events.

The script is broken into two parts:

  1. Mobile camera events, which rely on touch events
  2. Non-mobile camera events, which rely on keyboard input and tracking the user's movement

First, the camera script needs utility functions to setup the camera and set its Camera.CameraType to Scriptable so that the script can control the camera. It also needs a function to update the camera when it moves, rotates, and zooms.

Using touch events allows us to track user input as they interact with the touchscreen on their mobile device. These events allow us to handle camera movement, rotation, and zoom.

The second half of the code sample adds camera support for players on desktop devices. When input begans, the function Input() checks that the state of the input is Enum.UserInputState.Begin to ignore all keypress inputs other than when the user first presses a key down. When the user presses I and O the camera zooms in and out. When the presses down and moves their left mouse button, the script locks the player's mouse by changing the UserInputService.MouseBehavior property. The camera rotates according to the mouse's change in screen position. When the player moves their character, the camera moves with them.

All of the parts discussed above are combined and shown in the code sample below.

Create a Custom CameraScript

local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local camera = workspace.CurrentCamera
local player = Players.LocalPlayer
local character = player.CharacterAdded:Wait()
local torso = character:WaitForChild("HumanoidRootPart")
local playerPosition = torso.Position
local default_CameraPosition = torso.Position
local default_CameraRotation = Vector2.new(0, math.rad(-60))
local default_CameraZoom = 15
local cameraPosition = default_CameraPosition
local cameraRotation = default_CameraRotation
local cameraZoom = default_CameraZoom
local cameraZoomBounds = nil -- {10,200}
local cameraRotateSpeed = 10
local cameraMouseRotateSpeed = 0.25
local cameraTouchRotateSpeed = 10
local function SetCameraMode()
camera.CameraType = "Scriptable"
camera.FieldOfView = 80
camera.CameraSubject = nil
end
local function UpdateCamera()
SetCameraMode()
local cameraRotationCFrame = CFrame.Angles(0, cameraRotation.X, 0) * CFrame.Angles(cameraRotation.Y, 0, 0)
camera.CFrame = cameraRotationCFrame + cameraPosition + cameraRotationCFrame * Vector3.new(0, 0, cameraZoom)
camera.Focus = camera.CFrame - Vector3.new(0, camera.CFrame.p.Y, 0)
end
local lastTouchTranslation = nil
local function TouchMove(_touchPositions, totalTranslation, _velocity, state)
if state == Enum.UserInputState.Change or state == Enum.UserInputState.End then
local difference = totalTranslation - lastTouchTranslation
cameraPosition = cameraPosition + Vector3.new(difference.X, 0, difference.Y)
UpdateCamera()
end
lastTouchTranslation = totalTranslation
end
local lastTouchRotation = nil
local function TouchRotate(_touchPositions, rotation, _velocity, state)
if state == Enum.UserInputState.Change or state == Enum.UserInputState.End then
local difference = rotation - lastTouchRotation
cameraRotation = cameraRotation
+ Vector2.new(-difference, 0) * math.rad(cameraTouchRotateSpeed * cameraRotateSpeed)
UpdateCamera()
end
lastTouchRotation = rotation
end
local lastTouchScale = nil
local function TouchZoom(_touchPositions, scale, _velocity, state)
if state == Enum.UserInputState.Change or state == Enum.UserInputState.End then
local difference = scale - lastTouchScale
cameraZoom = cameraZoom * (1 + difference)
if cameraZoomBounds ~= nil then
cameraZoom = math.min(math.max(cameraZoom, cameraZoomBounds[1]), cameraZoomBounds[2])
else
cameraZoom = math.max(cameraZoom, 0)
end
UpdateCamera()
end
lastTouchScale = scale
end
local function Input(inputObject)
if inputObject.UserInputType == Enum.UserInputType.Keyboard then
if inputObject.UserInputState == Enum.UserInputState.Begin then
-- (I) Zoom In
if inputObject.KeyCode == Enum.KeyCode.I then
cameraZoom = cameraZoom - 15
elseif inputObject.KeyCode == Enum.KeyCode.O then
cameraZoom = cameraZoom + 15
end
-- (O) Zoom Out
if cameraZoomBounds ~= nil then
cameraZoom = math.min(math.max(cameraZoom, cameraZoomBounds[1]), cameraZoomBounds[2])
else
cameraZoom = math.max(cameraZoom, 0)
end
UpdateCamera()
end
end
local pressed = UserInputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton1)
if pressed then
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCurrentPosition
local rotation = UserInputService:GetMouseDelta()
cameraRotation = cameraRotation + rotation * math.rad(cameraMouseRotateSpeed)
else
UserInputService.MouseBehavior = Enum.MouseBehavior.Default
end
end
local function PlayerChanged()
local movement = torso.Position - playerPosition
cameraPosition = cameraPosition + movement
playerPosition = torso.Position
UpdateCamera()
end
-- Determine whether the user is on a mobile device
if UserInputService.TouchEnabled then
-- The user is on a mobile device, use Touch events
UserInputService.TouchPan:Connect(TouchMove)
UserInputService.TouchRotate:Connect(TouchRotate)
UserInputService.TouchPinch:Connect(TouchZoom)
else
-- The user is not on a mobile device use Input events
UserInputService.InputBegan:Connect(Input)
UserInputService.InputChanged:Connect(Input)
UserInputService.InputEnded:Connect(Input)
-- Camera controlled by player movement
task.wait(2)
RunService:BindToRenderStep("PlayerChanged", Enum.RenderPriority.Camera.Value - 1, PlayerChanged)
end

TouchRotate

触摸旋转事件会在用户在 TouchEnabled 设备上旋转两个手指时触发。

例如,以下代码打印了相机自触摸旋转开始以来旋转了多少。


local UserInputService = game:GetService("UserInputService")
UserInputService.TouchRotate:Connect(function(touchPositions, rotation, velocity, state, gameProcessedEvent)
print("Camera has rotated " .. tostring(rotation) .. " degrees!")
end)

要检查用户的设备是否启用触摸,并且触摸事件会触发,请参阅 UserInputService.TouchEnabled

此事件仅在 Roblox 客户端窗口处于焦点时发生。例如,窗口被最小化时,输入不会被捕获。

由于此事件仅在本地发射,它只能在 LocalScript 中使用。

在移动设备上控制用户的相机的核心脚本使用与此事件相似的功能代码。对于此事件,最佳实践是在创建移动相机系统时使用它来覆盖默认核心脚本。

还见:

参数

touchPositions: Array

一个 Vector2s 阵列,表示参与手势的手指位置。

rotation: number

该手势旋转以来的度数。

velocity: number

旋转变化(以度计)除以更改持续时间(以秒计)。

gameProcessedEvent: boolean

指示游戏引擎是否内部观察到此输入并采取行动。一般来说,这指的是 UI 处理,因此如果从这个输入触摸或单击了按钮,那么 gameProcessedEvent 将是 true。这也适用于通过 ContextActionService 连接的输入事件。


代码示例

By default, Roblox relies on a LocalScript to control the user's camera. However, this script can be overridden with a custom CameraScript. The example below demonstrates how to create a custom script to control the user's camera using many of the UserInputService events.

The script is broken into two parts:

  1. Mobile camera events, which rely on touch events
  2. Non-mobile camera events, which rely on keyboard input and tracking the user's movement

First, the camera script needs utility functions to setup the camera and set its Camera.CameraType to Scriptable so that the script can control the camera. It also needs a function to update the camera when it moves, rotates, and zooms.

Using touch events allows us to track user input as they interact with the touchscreen on their mobile device. These events allow us to handle camera movement, rotation, and zoom.

The second half of the code sample adds camera support for players on desktop devices. When input begans, the function Input() checks that the state of the input is Enum.UserInputState.Begin to ignore all keypress inputs other than when the user first presses a key down. When the user presses I and O the camera zooms in and out. When the presses down and moves their left mouse button, the script locks the player's mouse by changing the UserInputService.MouseBehavior property. The camera rotates according to the mouse's change in screen position. When the player moves their character, the camera moves with them.

All of the parts discussed above are combined and shown in the code sample below.

Create a Custom CameraScript

local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local camera = workspace.CurrentCamera
local player = Players.LocalPlayer
local character = player.CharacterAdded:Wait()
local torso = character:WaitForChild("HumanoidRootPart")
local playerPosition = torso.Position
local default_CameraPosition = torso.Position
local default_CameraRotation = Vector2.new(0, math.rad(-60))
local default_CameraZoom = 15
local cameraPosition = default_CameraPosition
local cameraRotation = default_CameraRotation
local cameraZoom = default_CameraZoom
local cameraZoomBounds = nil -- {10,200}
local cameraRotateSpeed = 10
local cameraMouseRotateSpeed = 0.25
local cameraTouchRotateSpeed = 10
local function SetCameraMode()
camera.CameraType = "Scriptable"
camera.FieldOfView = 80
camera.CameraSubject = nil
end
local function UpdateCamera()
SetCameraMode()
local cameraRotationCFrame = CFrame.Angles(0, cameraRotation.X, 0) * CFrame.Angles(cameraRotation.Y, 0, 0)
camera.CFrame = cameraRotationCFrame + cameraPosition + cameraRotationCFrame * Vector3.new(0, 0, cameraZoom)
camera.Focus = camera.CFrame - Vector3.new(0, camera.CFrame.p.Y, 0)
end
local lastTouchTranslation = nil
local function TouchMove(_touchPositions, totalTranslation, _velocity, state)
if state == Enum.UserInputState.Change or state == Enum.UserInputState.End then
local difference = totalTranslation - lastTouchTranslation
cameraPosition = cameraPosition + Vector3.new(difference.X, 0, difference.Y)
UpdateCamera()
end
lastTouchTranslation = totalTranslation
end
local lastTouchRotation = nil
local function TouchRotate(_touchPositions, rotation, _velocity, state)
if state == Enum.UserInputState.Change or state == Enum.UserInputState.End then
local difference = rotation - lastTouchRotation
cameraRotation = cameraRotation
+ Vector2.new(-difference, 0) * math.rad(cameraTouchRotateSpeed * cameraRotateSpeed)
UpdateCamera()
end
lastTouchRotation = rotation
end
local lastTouchScale = nil
local function TouchZoom(_touchPositions, scale, _velocity, state)
if state == Enum.UserInputState.Change or state == Enum.UserInputState.End then
local difference = scale - lastTouchScale
cameraZoom = cameraZoom * (1 + difference)
if cameraZoomBounds ~= nil then
cameraZoom = math.min(math.max(cameraZoom, cameraZoomBounds[1]), cameraZoomBounds[2])
else
cameraZoom = math.max(cameraZoom, 0)
end
UpdateCamera()
end
lastTouchScale = scale
end
local function Input(inputObject)
if inputObject.UserInputType == Enum.UserInputType.Keyboard then
if inputObject.UserInputState == Enum.UserInputState.Begin then
-- (I) Zoom In
if inputObject.KeyCode == Enum.KeyCode.I then
cameraZoom = cameraZoom - 15
elseif inputObject.KeyCode == Enum.KeyCode.O then
cameraZoom = cameraZoom + 15
end
-- (O) Zoom Out
if cameraZoomBounds ~= nil then
cameraZoom = math.min(math.max(cameraZoom, cameraZoomBounds[1]), cameraZoomBounds[2])
else
cameraZoom = math.max(cameraZoom, 0)
end
UpdateCamera()
end
end
local pressed = UserInputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton1)
if pressed then
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCurrentPosition
local rotation = UserInputService:GetMouseDelta()
cameraRotation = cameraRotation + rotation * math.rad(cameraMouseRotateSpeed)
else
UserInputService.MouseBehavior = Enum.MouseBehavior.Default
end
end
local function PlayerChanged()
local movement = torso.Position - playerPosition
cameraPosition = cameraPosition + movement
playerPosition = torso.Position
UpdateCamera()
end
-- Determine whether the user is on a mobile device
if UserInputService.TouchEnabled then
-- The user is on a mobile device, use Touch events
UserInputService.TouchPan:Connect(TouchMove)
UserInputService.TouchRotate:Connect(TouchRotate)
UserInputService.TouchPinch:Connect(TouchZoom)
else
-- The user is not on a mobile device use Input events
UserInputService.InputBegan:Connect(Input)
UserInputService.InputChanged:Connect(Input)
UserInputService.InputEnded:Connect(Input)
-- Camera controlled by player movement
task.wait(2)
RunService:BindToRenderStep("PlayerChanged", Enum.RenderPriority.Camera.Value - 1, PlayerChanged)
end

TouchStarted

当用户将手指放在 TouchEnabled 设备上时,触摸开始事件发生,开始使用设备进行触摸输入

这个事件可以用来确定用户何时开始触摸他们设备的屏幕。它可以与 UserInputService.TouchEnded 匹配,以确定用户何时开始和停止触摸屏幕。

触摸输入对象在触摸期间始终是相同的输入对象。因此,当触摸对象时比较 InputObjects 是有效的,以确定它是否是同一只手指。

要检查用户的设备是否启用触摸,并且触摸事件会触发,请参阅 UserInputService.TouchEnabled

此事件仅在 Roblox 客户端窗口处于焦点时发生。例如,窗口被最小化时,输入不会被捕获。

由于此事件仅在本地发射,它只能在 LocalScript 中使用。

还见:

参数

包含用户输入信息的 InputObject 实例。

gameProcessedEvent: boolean

指示游戏引擎是否内部观察到此输入并采取行动。一般来说,这指的是 UI 处理,因此如果从这个输入触摸或单击了按钮,那么 gameProcessedEvent 将是 true。这也适用于通过 ContextActionService 连接的输入事件。


代码示例

This example demonstrates how to use touch input events to drag a GUI element while a player touches and drags across their screen.

The touch InputObject is the same input object throughout the lifetime of the touch. So comparing input objects when they are touch objects is valid to determine if it is the same touch as the input starts, changes, and ends.

The example starts tracking a drag once the touch is registered by the TouchStarted() event. It continues to update as that touch moves, tracking its position relative to start position to move a GUI until a TouchEvent event fires for that touch.

Tracking Touches

local UserInputService = game:GetService("UserInputService")
local dragging
local dragInput
local dragStart
local startPos
local gui = script.Parent
local function touchStarted(input, _gameProcessed)
if not dragging then
dragging = true
dragInput = input
dragStart = input.Position
startPos = gui.Position
end
end
local function update(input, _gameProcessed)
if input == dragInput and dragging then
local delta = input.Position - dragStart
gui.Position =
UDim2.new(startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y)
end
end
local function touchEnded(input, _gameProcessed)
if input == dragInput then
dragging = false
end
end
UserInputService.TouchStarted:Connect(touchStarted)
UserInputService.TouchMoved:Connect(update)
UserInputService.TouchEnded:Connect(touchEnded)

TouchSwipe

当用户在设备上滑动手指时,TouchSwipe会发生,当用户滑动手指时,TouchEnabled会发生。

该事件可用于确定用户在设备屏幕上滑动手指的时间和方向,以及用户滑动的方向。

要更精确地跟踪触摸输入移动,请使用 UserInputService.TouchMoved

要检查用户的设备是否启用触摸,并且触摸事件会触发,请参阅 UserInputService.TouchEnabled

此事件仅在 Roblox 客户端窗口处于焦点时发生。例如,窗口被最小化时,输入不会被捕获。

由于此事件仅在本地发射,它只能在 LocalScript 中使用。

还见:

参数

swipeDirection: Enum.SwipeDirection

一个 Enum.SwipeDirection , 指示用户滑动的方向。

numberOfTouches: number

参与手势的触摸数(例如手指)。

gameProcessedEvent: boolean

指示游戏引擎是否内部观察到此输入并采取行动。一般来说,这指的是 UI 处理,因此如果从这个输入触摸或单击了按钮,那么 gameProcessedEvent 将是 true。这也适用于通过 ContextActionService 连接的输入事件。


代码示例

The example below demonstrates the TouchSwipe() event by tweening a GuiObject|GUI element's position 100 pixels in the direction of the swipe according to the value of the swipeDirection argument.

In order for this example to work as expected, it must be placed in a LocalScript that is parented to the gui being swiped.

Touch Swipe a GUI

local UserInputService = game:GetService("UserInputService")
local gui = script.Parent
local swipePositionY = gui.Position.Y.Offset
local swipePositionX = gui.Position.X.Offset
local camera = workspace.CurrentCamera
local maxY = camera.ViewportSize.Y - gui.Size.Y.Offset
local maxX = camera.ViewportSize.X - gui.Size.X.Offset
local function TouchSwipe(swipeDirection, _numberOfTouches, _gameProcessedEvent)
if swipeDirection == Enum.SwipeDirection.Up then
swipePositionY = math.max(swipePositionY - 200, 0)
elseif swipeDirection == Enum.SwipeDirection.Down then
swipePositionY = math.min(swipePositionY + 200, maxY)
elseif swipeDirection == Enum.SwipeDirection.Left then
swipePositionX = math.max(swipePositionX - 200, 0)
elseif swipeDirection == Enum.SwipeDirection.Right then
swipePositionX = math.min(swipePositionX + 200, maxX)
end
gui:TweenPosition(UDim2.new(0, swipePositionX, 0, swipePositionY), "Out", "Quad", 0.25, true)
end
UserInputService.TouchSwipe:Connect(TouchSwipe)

TouchTap

触摸事件在 TouchEnabled 设备上的屏幕上触摸/点击用户的手指时触发。

无论用户是否触摸/点击游戏世界或 GuiObject 元素,此事件都会发射。如果您正在寻找仅在用户触摸/点击游戏世界时发射的事件,请使用 UserInputService.TouchTapInWorld

要检查用户的设备是否启用触摸,并且触摸事件会触发,请参阅 UserInputService.TouchEnabled

此事件仅在 Roblox 客户端窗口处于焦点时发生。例如,窗口被最小化时,输入不会被捕获。

由于此事件仅在本地发射,它只能在 LocalScript 中使用。

参数

touchPositions: Array

一个由 Vector2 个对象组成的阵列,表示敲击手势中涉及的手指位置。

gameProcessedEvent: boolean

指示游戏引擎是否内部观察到此输入并采取行动。一般来说,这指的是 UI 处理,因此如果从这个输入触摸或单击了按钮,那么 gameProcessedEvent 将是 true。这也适用于通过 ContextActionService 连接的输入事件。


代码示例

The code sample below demonstrates the difference between a TouchTap() and TouchLongPress() by creating a GuiObject|GUI Frame that appears when user touches the screen of their device and disappears when the Class.UserInputEvent.TouchEnded|touch ends. When the long press event fires, the GUI doubles in size. Also, the GUI moves to stay centered under the user's finger when the player moves their finger.

In order for the TouchLongPress() to fire, the user touch the screen and hold their finger still for a short period of time. Once the touch moves, the long press event will not fire.

In order for the example to work as expected, it should be placed in a LocalScript that is parented to a ScreenGui.

The Difference Between TouchTap and TouchLongPress

local UserInputService = game:GetService("UserInputService")
-- The parent of this script (a ScreenGui)
local touchScreenGui = script.Parent
-- Create the GUI frame that the user interacts with through Touch
-- events
local touchGui = Instance.new("Frame")
touchGui.Name = "TouchGui"
touchGui.AnchorPoint = Vector2.new(0.5, 0.5)
-- Fires when the touches their device's screen
local function TouchTap(touchPositions, _gameProcessedEvent)
touchGui.Parent = touchScreenGui
touchGui.Position = UDim2.new(0, touchPositions[1].X, 0, touchPositions[1].Y)
touchGui.Size = UDim2.new(0, 50, 0, 50)
end
-- Fires when a user starts touching their device's screen and does not
-- move their finger for a short period of time
local function TouchLong(_touchPositions, _state, _gameProcessedEvent)
touchGui.Size = UDim2.new(0, 100, 0, 100)
end
-- Fires when the user moves their finger while touching their device's
-- screen
local function TouchMove(touch, _gameProcessedEvent)
touchGui.Position = UDim2.new(0, touch.Position.X, 0, touch.Position.Y)
end
-- Fires when the user stops touching their device's screen
local function TouchEnd(_touch, _gameProcessedEvent)
touchGui.Parent = nil
touchGui.Size = UDim2.new(0, 50, 0, 50)
end
-- Only use the Touch events if the user is on a mobile device
if UserInputService.TouchEnabled then
UserInputService.TouchTap:Connect(TouchTap)
UserInputService.TouchLongPress:Connect(TouchLong)
UserInputService.TouchMoved:Connect(TouchMove)
UserInputService.TouchEnded:Connect(TouchEnd)
end

TouchTapInWorld

触摸世界事件在用户在 TouchEnabled 设备上触摸/点击屏幕时触发。当用户点击游戏世界时,它会被发射。

这个事件可以用来确定用户点击屏幕时是否没有点击GuiObject元素。如果用户点击 GUI 元素,UserInputService.TouchTap 会在 TouchTapInWorld 之前发射。

要检查用户的设备是否启用触摸,并且触摸事件会触发,请参阅 UserInputService.TouchEnabled

此事件仅在 Roblox 客户端窗口处于焦点时发生。例如,窗口被最小化时,输入不会被捕获。

由于它只能在本地发射,它只能在 LocalScript 中使用。

还见:

参数

position: Vector2

一个 Vector2 指示触摸位置的。

processedByUI: boolean

用户是否点击了图形用户界面元素。


代码示例

This example uses the Vector2 position passed by TouchTapInWorld() to find the Vector3 world position the user tapped. Then, the code spawns an anchored BasePart|Part at the world position.

In order to calculate the Vector3 world position using the viewport position, this example generates a Ray called unitRay originating from position using the ViewportPointToRay() function. Then, since ViewportPointToRay() creates a unit ray that is only 1 stud long, the example uses it to create a longer ray that is length studs long. Using FindPartOnRay(), the code determines where the ray first intersects a part in the world - the Vector3 world position that the user tapped.

Note that the code sample will not spawn a part if the user touches on the screen over an empty skybox. The touch must be on a part for FindPartOnRay() to return a Vector3 position.

Create a Part in World at Touch Position

local UserInputService = game:GetService("UserInputService")
local camera = workspace.CurrentCamera
local LENGTH = 500
local function createPart(position, processedByUI)
-- Do not create a part if the player clicked on a GUI/UI element
if processedByUI then
return
end
-- Get Vector3 world position from the Vector2 viewport position
local unitRay = camera:ViewportPointToRay(position.X, position.Y)
local ray = Ray.new(unitRay.Origin, unitRay.Direction * LENGTH)
local hitPart, worldPosition = workspace:FindPartOnRay(ray)
-- Create a new part at the world position if the player clicked on a part
-- Do not create a new part if player clicks on empty skybox
if hitPart then
local part = Instance.new("Part")
part.Parent = workspace
part.Anchored = true
part.Size = Vector3.new(1, 1, 1)
part.Position = worldPosition
end
end
UserInputService.TouchTapInWorld:Connect(createPart)

WindowFocusReleased

当 Roblox 客户端窗口失去焦点时,UserInputService 窗口焦点释放事件发生 - 通常是当 Roblox 客户端被用户最小化时。

例如,下面的代码每当 Roblox 客户端失去焦点时打印 “窗口焦点释放”


local UserInputService = game:GetService("UserInputService")
UserInputService.WindowFocusReleased:Connect(function()
print("Window focus released")
end)

此事件可以与 UserInputService.WindowFocused 一起使用,以跟踪 Roblox 客户端是否积极关注用户的屏幕。

由于它只能在本地发射,它只能在 LocalScript 中使用。


代码示例

This example fires a RemoveEvent to the server name AfkEvent when the LocalPlayer's client gains or loses focus.

The purpose of this code sample is to fire a server-side event to indicate when the player is AFK. This is indicated by spawning a ForceField around the player when the client loses focus and destroying the forcefield when the client gains focus.

In order for this example to work as expected, the code labelled LocalScript must be placed in a LocalScript and the code labelled Script must be placed in a Script. This sample is a Script which should be run in conjunction with the LocalScript code sample: Window Focus AFK Script (LocalScript)

Window Focus AFK Script (Script)

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local afkEvent = Instance.new("RemoteEvent")
afkEvent.Name = "AfkEvent"
afkEvent.Parent = ReplicatedStorage
local function setAfk(player, afk)
if afk then
local forcefield = Instance.new("ForceField")
forcefield.Parent = player.Character
else
local forcefield = player.Character:FindFirstChildOfClass("ForceField")
if forcefield then
forcefield:Destroy()
end
end
end
afkEvent.OnServerEvent:Connect(setAfk)

This sample is a LocalScript which should be run in conjunction with the Script code sample: Window Focus AFK Script (Script)

Window Focus AFK Script (LocalScript)

local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local afkEvent = ReplicatedStorage:WaitForChild("AfkEvent")
local function focusGained()
afkEvent:FireServer(false)
end
local function focusReleased()
afkEvent:FireServer(true)
end
UserInputService.WindowFocused:Connect(focusGained)
UserInputService.WindowFocusReleased:Connect(focusReleased)

WindowFocused

当 Roblox 客户端窗口获得焦点时,UserInputService会发生,通常是当 Roblox 客户端最大化/在用户屏幕上打开时。

例如,下面的代码每当 Roblox 客户端获得焦点时打印 “窗口聚焦”


local UserInputService = game:GetService("UserInputService")
UserInputService.WindowFocused:Connect(function()
print("Window focused")
end)

此事件可以与 UserInputService.WindowFocusReleased 一起使用,以跟踪 Roblox 客户端是否积极关注用户的屏幕。

由于此事件仅在本地发射,它只能在 LocalScript 中使用。


代码示例

This example fires a RemoveEvent to the server name AfkEvent when the LocalPlayer's client gains or loses focus.

The purpose of this code sample is to fire a server-side event to indicate when the player is AFK. This is indicated by spawning a ForceField around the player when the client loses focus and destroying the forcefield when the client gains focus.

In order for this example to work as expected, the code labelled LocalScript must be placed in a LocalScript and the code labelled Script must be placed in a Script. This sample is a Script which should be run in conjunction with the LocalScript code sample: Window Focus AFK Script (LocalScript)

Window Focus AFK Script (Script)

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local afkEvent = Instance.new("RemoteEvent")
afkEvent.Name = "AfkEvent"
afkEvent.Parent = ReplicatedStorage
local function setAfk(player, afk)
if afk then
local forcefield = Instance.new("ForceField")
forcefield.Parent = player.Character
else
local forcefield = player.Character:FindFirstChildOfClass("ForceField")
if forcefield then
forcefield:Destroy()
end
end
end
afkEvent.OnServerEvent:Connect(setAfk)

This sample is a LocalScript which should be run in conjunction with the Script code sample: Window Focus AFK Script (Script)

Window Focus AFK Script (LocalScript)

local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local afkEvent = ReplicatedStorage:WaitForChild("AfkEvent")
local function focusGained()
afkEvent:FireServer(false)
end
local function focusReleased()
afkEvent:FireServer(true)
end
UserInputService.WindowFocused:Connect(focusGained)
UserInputService.WindowFocusReleased:Connect(focusReleased)