Repository navigation
Player
The built-in PlayerController already handles walking, mouse look, jumping, sprinting
(LShift + W) and no-clip (V). These scripts tweak it by reading and writing its properties, or
by nudging the player's Rigidbody.
In the usual setup the player Entity carries the PlayerController, Rigidbody, and
Camera components, so an entity script on it can reach them through
entity.playerController, entity.rigidbody, and entity.camera. Each of these is
nil if the component is missing.
Attach to: the player.
Hold a key to walk slowly with a lower eye height.
-- Scripts/Player/Crouch.lua (entity script)
public Key crouchKey = Key.LCtrl
public number crouchSpeed = 22
public number crouchEyeHeight = 6
local pc
local standingSpeed, standingRunSpeed, standingEye
function Start()
pc = entity.playerController
if pc == nil then
Debug.LogError("Crouch: " .. entity.name .. " has no PlayerController")
return
end
standingSpeed = pc.speed
standingRunSpeed = pc.runningSpeed
standingEye = pc.eyeHeight
end
function Update()
if pc == nil then return end
if Input.GetKey(crouchKey) then
pc.speed = crouchSpeed
pc.runningSpeed = crouchSpeed -- no sprinting while crouched
pc.eyeHeight = crouchEyeHeight
else
pc.speed = standingSpeed
pc.runningSpeed = standingRunSpeed
pc.eyeHeight = standingEye
end
endNotes
- The standing values are captured in
Startso the script respects whatever you set in the inspector. - Nothing here checks for a low ceiling above the player, so standing up can clip into a ceiling.
- Other scripts that write
speed,runningSpeedoreyeHeight(like the speed zone below, or the head bob in 16_camera_effects.md) will fight this one.
Attach to: the player.
The controller handles the first jump from the ground. This script adds extra jumps in the air by overwriting the vertical velocity.
-- Scripts/Player/DoubleJump.lua (entity script)
public int extraJumps = 1
public Key jumpKey = Key.Space
local rb, pc
local jumpsLeft = 0
function Start()
rb = entity.rigidbody
pc = entity.playerController
jumpsLeft = extraJumps
end
function Update()
if rb == nil or pc == nil then return end
if rb.isGrounded then
jumpsLeft = extraJumps
elseif jumpsLeft > 0 and Input.GetKeyDown(jumpKey) then
local v = rb.velocity
rb.velocity = Vector3(v.x, pc.jumpPower, v.z)
jumpsLeft = jumpsLeft - 1
end
endNotes
-
local v = rb.velocityis a copy, so build a newVector3and assign it back. Keepingv.xandv.zpreserves the controller's horizontal movement. (rb.velocity.y = pc.jumpPowerwould also work.) - Make the extra jump stronger or weaker than the first by using a different number instead of
pc.jumpPower.
Attach to: a sector.
While the player stands inside this sector their speed is multiplied. It goes back to normal when they leave.
-- Scripts/Player/SpeedZone.lua (sector script)
public Entity player = nil
public number multiplier = 1.6
local pc
local baseSpeed, baseRunSpeed
local boosted = false
local function PlayerIsInside()
for i = 1, sector.entityCount do
if sector:GetEntity(i).id == player.id then return true end
end
return false
end
local function Restore()
if boosted then
pc.speed = baseSpeed
pc.runningSpeed = baseRunSpeed
boosted = false
end
end
function Start()
if player == nil then
Debug.LogWarning("SpeedZone in sector " .. sector.id .. " has no player assigned")
return
end
pc = player.playerController
if pc == nil then return end
baseSpeed = pc.speed
baseRunSpeed = pc.runningSpeed
end
function Update()
if pc == nil then return end
local inside = PlayerIsInside()
if inside and not boosted then
pc.speed = baseSpeed * multiplier
pc.runningSpeed = baseRunSpeed * multiplier
boosted = true
elseif not inside then
Restore()
end
end
function OnDisable()
if pc ~= nil then Restore() end
endNotes
-
sector.entityCountandsector:GetEntity(i)list the entities the engine currently places inside the sector, so no geometry math is needed. - The
OnDisablehook makes sure the player never keeps the bonus if the script is switched off while they're standing in the zone.
Attach to: a sector.
Launches the player upward when they stand on the sector.
-- Scripts/Player/JumpPad.lua (sector script)
public Entity player = nil
public number launchSpeed = 160
local rb
local function PlayerIsInside()
for i = 1, sector.entityCount do
if sector:GetEntity(i).id == player.id then return true end
end
return false
end
function Start()
if player ~= nil then rb = player.rigidbody end
end
function Update()
if rb == nil then return end
if rb.isGrounded and PlayerIsInside() then
local v = rb.velocity
rb.velocity = Vector3(v.x, launchSpeed, v.z)
Debug.Print("Boing!")
end
endNotes
- Because it only fires while
isGrounded, holding still on the pad launches once per landing. - Stronger pads (more
launchSpeed) may need a taller sector ceiling so the player doesn't hit their head.