Input and camera
Both belong to one player, so both are for ClientScripts. A server Script that touches input or camera gets an error saying so.
Keys
input.onKey("E", function() -- pressed (not while the player types in the chat or a text box)
net.send("interact")
end)
if input.isDown("LeftShift") then -- held right now?
print("sprinting")
endKey names: "A" to "Z", "Zero" to "Nine", "Space", "Return", "Tab", "Backspace", "Escape", "LeftShift", "RightShift", "LeftControl", "RightControl", "LeftAlt", "RightAlt", "Up", "Down", "Left", "Right".
For everything - mouse buttons too, and key releases - use the raw events:
input.began:connect(function(inputObject, typing)
if typing then return end -- the player is typing in the chat or a box
print(inputObject.type, inputObject.key)
end)
input.ended:connect(function(inputObject, typing)
if inputObject.key == "LeftShift" then print("stopped sprinting") end
end)Keys the game already uses
W A S D walk, Space jumps, Shift is camera lock, 1-0 pick tools, Tab the player list, Enter and / the chat, Esc the menu. Pick other keys for your game's own actions - E, F, Q, R...
On phones there is no keyboard: give every action a button on screen too (Scripting UI), or use a Prompt, which phones can tap.
What the mouse is over
game.frame:connect(function()
local hit = world:raycast(camera:ray()) -- from the camera through the pointer
if hit then
marker.position = hit.position
end
end)camera:ray(distance?) returns an origin and a direction through the pointer - the mouse, the middle of the screen in camera lock or first person, or the last touch - 1,000 units long unless you say.
The camera
Until a script changes it, the camera is the game's own: it follows the character, the mouse turns it, the wheel zooms, and it keeps out of walls.
| Member | What it is |
|---|---|
camera.mode | "Follow" (the game's camera), "Fixed" (stays where a script puts it), "FirstPerson" (always the eyes) |
camera.transform | Where it is and the way it looks. Setting it fixes the camera there |
camera.position | Where it is; setting it fixes the camera |
camera.fov | Field of view, 20 to 100 degrees (45 to start) |
camera.target | What "Follow" orbits: a part, another player, or nil for your own character |
camera.minZoom, camera.maxZoom | How near and far the wheel zooms, 0.5 to 400 units |
camera.offset | Moves the point the camera turns about (x right, y up, z behind) |
camera.firstPerson | True while the camera is the character's eyes (read-only) |
camera.firstPersonArms | In first person, draw the player's own arms (true) |
camera.viewportSize | The screen's size in UI points (read-only) |
camera:toScreen(position) | Where a point in the world is on the screen, and whether it is in front |
camera:tween(goals, time) | Smooth changes - a zoom, a cutscene |
Examples
-- An overhead camera
camera.transform = transform.lookAt(vec3(0, 60, 40), vec3(0, 0, 0))
camera.fov = 50
-- Back to normal
camera.mode = "Follow"-- A sprint that widens the view
input.began:connect(function(i, typing)
if not typing and i.key == "LeftShift" then camera:tween({fov = 60}, 0.2) end
end)
input.ended:connect(function(i)
if i.key == "LeftShift" then camera:tween({fov = 45}, 0.2) end
end)-- A cutscene: fly between two parts, then give the camera back
camera:tween({transform = world.Shot1.transform}, 2).completed:wait()
camera:tween({transform = world.Shot2.transform}, 3).completed:wait()
camera.mode = "Follow"-- Spectate another player
camera.target = someOtherPlayer-- A marker over a part, in screen UI
local where, inFront = camera:toScreen(world.Goal.position)
marker.visible = inFront
marker.position = dim.px(where.x, where.y)First person
Every world lets players zoom all the way in to first person, as Roblox does. To change how the camera starts for everyone, insert Camera settings (Insert > Camera settings) and set its Mode, Min zoom, Max zoom, Field of view, Arms in first person and Offset in the Inspector. A Min zoom of 2 or more keeps players out of first person.
A ClientScript changes its own player's camera from there:
-- A shooter: always first person, wide view, the pointer back for the shop
camera.mode = "FirstPerson"
camera.fov = 80
local shop = players.me.gui:waitFor("Shop")
input.onKey("B", function()
shop.visible = not shop.visible
input.mouseFree = shop.visible -- show the pointer while the shop is open
end)
game.frame:connect(function()
if camera.firstPerson then
local hit = world:raycast(camera:ray(300)) -- what the crosshair is on
end
end)Camera lock
Players press Shift (or the padlock button on phones) for camera lock: the camera sits over the right shoulder, the pointer is hidden with a crosshair in the middle, and the body always faces where the camera looks. camera:ray() then goes through the crosshair. input.mouseFree = true frees the pointer here too.