Skip to main content

Input

Input reads project Input Actions and physical PlayStation controller state. Prefer semantic names for gameplay so bindings can change without rewriting scripts; use physical constants for fixed platform conventions or diagnostics.

Buttons and Actions​

function Update(gameObjectId, deltaTime)
if Input.GetButtonDown("Interact") then
Log.Print("Interact pressed")
end
if Input.GetButton(Input.R1) then
Transform.RotateY(gameObjectId, 60.0 * deltaTime)
end
end
MethodDescription
Input.GetButton(buttonOrAction)Held state.
Input.GetButtonDown(buttonOrAction)True on the pressed frame.
Input.GetButtonUp(buttonOrAction)True on the released frame.

Physical constants are Input.CROSS, Input.CIRCLE, Input.SQUARE, Input.TRIANGLE, D-pad Input.UP, Input.DOWN, Input.LEFT, Input.RIGHT, Input.START, Input.SELECT, Input.L1, Input.L2, Input.L3, Input.R1, Input.R2, and Input.R3.

Axes​

Input.GetAxis(stickOrAction, deadZone) returns two numbers in -1.0..1.0:

local moveX, moveY = Input.GetAxis("Move")
local lookX, lookY = Input.GetAxis("Look")

-- Physical-stick access is also available.
local leftX, leftY = Input.GetAxis(Input.STICK_LEFT)

Use Input.STICK_LEFT or Input.STICK_RIGHT for direct physical-stick access.

Digital D-pad input feeds the movement path when the project binding allows it. The right stick requires an analog-capable pad in analog mode. Apply a project- appropriate dead zone before using small analog values.

Dead zones on physical controllers​

Original PS1 sticks do not always return exactly to the nominal center. A controller that works well in other games can still move the camera if your game uses a very small dead zone. Check this on the console as well as in an emulator.

For native controllers, adjust PlayerInput > Dead Zone in the Inspector. New native components start at 0.35. Last Exit uses its own Lua controller; adjust the exposed deadZone property on the player's LuaBehaviour. Its template default is 0.30, shared by movement and looking. Test 0.35 if a physical controller still drifts. Existing projects keep their saved values; updating the editor does not replace their scripts or component settings.

Custom Lua controllers can pass an optional dead zone directly:

local moveX, moveY = Input.GetAxis("Move", 0.35)
local lookX, lookY = Input.GetAxis("Look", 0.35)

The second argument is clamped to 0.0..0.95. Values inside the dead zone return zero; outside it, movement starts smoothly and still reaches full speed at full stick travel. Captured mouse look in Play Mode bypasses the stick dead zone. Do not apply a second dead zone to these filtered values. Omitting the argument keeps the original normalized, unfiltered axis values.

Use the smallest value that keeps the player and camera still with both sticks released across your test controllers. Rebuild the game with Build Disc Image (.bin + .cue) after changing scripts or scene settings; an existing disc image will retain the old values.

Device State​

MethodReturnsDescription
Input.IsConnected()booleanReports a supported device on Port 1.
Input.HasAnalog()booleanReports analog-stick availability.
Input.GetPadType()integerReturns the controller type code.

L3/R3 and rumble depend on the connected controller and emulator mapping. A game must remain operable when analog input or vibration is unavailable.

Configure semantic axes and buttons in Project Settings > Input Action Map. The PS1 build bakes at most 32 fixed action records and resolves action names without per-frame allocation.

PlayerInput Component State​

The PlayerInput table controls the authored PlayerInput component at runtime. It does not replace raw Input queries.

MethodReturnsDescription
PlayerInput.SetEnabled(gameObjectId, enabled)booleanEnables or disables native player movement, look, interaction, and interaction prompts. Returns false for an invalid GameObject or one without PlayerInput.
PlayerInput.IsEnabled(gameObjectId)boolean or nilReturns the runtime component state, or nil when PlayerInput is absent.

Disabling PlayerInput does not deactivate the GameObject or its LuaBehaviour. The script can continue reading Input to drive a modal menu, dialogue choice, cutscene skip, or other custom flow. The runtime state is restored from the authored component when a scene starts or reloads.

Locking the player and camera during dialogue​

Use Player Input on the player as the control switch. Replace "Player" in these examples with that GameObject's exact name. Keep the player, camera, and dialogue GameObjects active so the scene and dialogue can keep updating.

Native controllers​

For a native First Person Controller or Third Person Controller, disable PlayerInput when the dialogue opens and enable it after the dialogue closes:

-- When the dialogue opens:
PlayerInput.SetEnabled(GameObject.Find("Player"), false)

-- After the dialogue finishes closing:
PlayerInput.SetEnabled(GameObject.Find("Player"), true)

This stops native movement, camera look, and interaction. It does not disable raw Input queries, so the dialogue can still read buttons to advance text or choose an answer. Put these calls in your dialogue's open and close handlers; do not run both consecutively in the same handler. Restore input after the closing animation to avoid sending the closing button press to gameplay. If input was already disabled by another system, restore that previous state instead of unconditionally enabling it.

Lua movement and camera scripts​

Disabling PlayerInput does not stop custom Lua scripts. Keep a Player Input component on the player and use the same open/close calls above, then check its state before reading movement/look input or changing transforms. A Lua controller does not need Player Motor or a native controller for this switch.

Merge this pattern into each existing movement or camera script, caching the player ID in Start and adding the guard at the beginning of Update:

local player = -1

function Start(gameObjectId)
player = GameObject.Find("Player")
end

function Update(gameObjectId, deltaTime)
if PlayerInput.IsEnabled(player) == false then
return
end

-- Existing movement or camera code goes here.
end

If one script controls both the player and camera, one guard before both operations is enough. If they use separate scripts, add it to both. Apply the same guard to LateUpdate if that callback also moves or rotates the camera. Merge it with existing lifecycle functions instead of defining a second function with the same name. Keep the dialogue's own update running.

PlayerInput.IsEnabled returns nil when the component is missing, so check the GameObject name and component if the guard has no effect. This is an input lock, not a world pause: gravity, animations, and other scripts can still run. Opening a canvas alone does not block the player or custom camera controls.

After changing scripts or components, rebuild with Build Disc Image (.bin + .cue) to test the same behavior on PS1 or DuckStation.