VR Input System (EasyInputs)
Hand Parameter
All input functions that require a hand use: Enum.Hand.Left or Enum.Hand.Right
Grip & Trigger
Input.GetGripButtonDown(hand)
Returns true if the grip button is pressed
hand - Enum.Hand.Left or Enum.Hand.Right
Returns: boolean
Input.GetGripButtonFloat(hand)
Returns analog grip value (useful for grip strength)
Returns: float (0.0 to 1.0)
Input.LeftGrip() / Input.RightGrip()
Convenience shortcuts for grip values
Returns: float (0.0 to 1.0)
Input.GetTriggerButtonDown(hand)
Returns true if trigger button is pressed
Returns: boolean
Input.GetTriggerButtonFloat(hand)
Returns analog trigger value
Returns: float (0.0 to 1.0)
Input.GetTriggerButtonTouched(hand)
Returns true if trigger is being touched (Quest only)
Returns: boolean
Input.LeftTrigger() / Input.RightTrigger()
Convenience shortcuts for trigger values
Returns: float (0.0 to 1.0)
Face Buttons (A, B, X, Y)
Input.GetPrimaryButtonDown(hand)
A button (right hand) or X button (left hand)
Returns: boolean
Input.GetSecondaryButtonDown(hand)
B button (right hand) or Y button (left hand)
Returns: boolean
Input.AButton() / Input.BButton()
Right controller buttons (A and B)
Returns: boolean
Input.XButton() / Input.YButton()
Left controller buttons (X and Y)
Returns: boolean
Input.GetPrimaryButtonTouched(hand)
Returns true if primary button is being touched
Returns: boolean
Input.GetSecondaryButtonTouched(hand)
Returns true if secondary button is being touched
Returns: boolean
Thumbstick
Input.GetThumbStick2DAxis(hand)
Get thumbstick position as Vector2 (for movement/turning)
Returns: Vector2 (x: -1 to 1, y: -1 to 1)
Input.LeftStick() / Input.RightStick()
Convenience shortcuts for thumbstick values
Returns: Vector2
Input.GetThumbStickButtonDown(hand)
Returns true if thumbstick is clicked down
Returns: boolean
Input.GetThumbStickButtonTouched(hand)
Returns true if thumbstick is being touched
Returns: boolean
Menu & System
Input.GetMenuButtonDown(hand)
Returns true if menu button is pressed
Returns: boolean
Device Tracking
Input.GetDeviceVelocity(hand)
Get controller velocity (useful for swing detection)
Returns: Vector3
Input.LeftControllerPosition()
Get left controller world position
Returns: Vector3
Input.RightControllerPosition()
Get right controller world position
Returns: Vector3
Input.LeftControllerRotation()
Get left controller rotation
Returns: Quaternion
Input.RightControllerRotation()
Get right controller rotation
Returns: Quaternion
Input.HeadsetPosition()
Get VR headset position
Returns: Vector3
Input.HeadsetRotation()
Get VR headset rotation
Returns: Quaternion
Haptics
Input.Vibrate(hand, amplitude, duration)
Trigger haptic feedback on controller
hand - Which controller
amplitude - Vibration strength (0.0 to 1.0)
duration - Duration in seconds
amplitude - Vibration strength (0.0 to 1.0)
duration - Duration in seconds
Example: VR Input Usage
-- Check if right trigger is pulledif Input.RightTrigger() > 0.5 then
print("Trigger pulled!")
end
-- Get thumbstick for movement
local stick = Input.LeftStick()
print("Stick X: " .. stick.x .. " Y: " .. stick.y)
-- Check button press
if Input.AButton() then
print("A button pressed!")
Input.Vibrate(Enum.Hand.Right, 0.5, 0.1)
end
-- Detect controller swing
local velocity = Input.GetDeviceVelocity(Enum.Hand.Right)
if velocity.magnitude > 2.0 then
print("Fast swing detected!")
end
GameObject Management
GameObject.New(name)
Create a new empty GameObject
name - GameObject name
Returns: GameObject
GameObject.Find(name)
Find a GameObject by name in the scene
Returns: GameObject or nil
GameObject.FindWithTag(tag)
Find first GameObject with specified tag
Returns: GameObject or nil
GameObject.FindGameObjectsWithTag(tag)
Find all GameObjects with specified tag
Returns: GameObject array
GameObject.CreatePrimitive(type)
Create a primitive shape
type - Enum.Primitive.Sphere, Cube, Cylinder, Capsule, Plane, Quad
Returns: GameObject
GameObject.Destroy(obj)
Destroy a GameObject (happens at end of frame)
GameObject.DestroyImmediate(obj)
Destroy a GameObject immediately
GameObject.DontDestroyOnLoad(obj)
Keep GameObject alive between scene loads
Example: Creating Objects
-- Create a spherelocal sphere = GameObject.CreatePrimitive(Enum.Primitive.Sphere)
sphere.transform.position = Vector3.New(0, 2, 5)
sphere.transform.localScale = Vector3.New(2, 2, 2)
-- Find and modify existing object
local player = GameObject.Find("Player")
if player then
print("Found player at: " .. player.transform.position)
end
-- Find all enemies
local enemies = GameObject.FindGameObjectsWithTag("Enemy")
print("Found " .. #enemies .. " enemies")
Triggers & Collisions
Trigger System
Trigger.Add(gameObject)
Add trigger component to GameObject (auto-adds collider as trigger)
Returns: LuaTrigger component
Trigger.SetTag(trigger, tag)
Filter triggers to only detect specific tag
Trigger.OnEnter(trigger, callback)
Set callback when something enters trigger
callback - function(otherGameObject)
Trigger.OnExit(trigger, callback)
Set callback when something exits trigger
Trigger.OnStay(trigger, callback)
Set callback while something stays in trigger (called every frame)
Collision System
Collision.Add(gameObject)
Add collision component (auto-adds collider and rigidbody)
Returns: LuaCollision component
Collision.SetTag(collision, tag)
Filter collisions to only detect specific tag
Collision.OnEnter(collision, callback)
Set callback when collision starts
Collision.OnExit(collision, callback)
Set callback when collision ends
Collision.OnStay(collision, callback)
Set callback while collision continues
Example: Trigger Zone
-- Create a trigger zonelocal zone = GameObject.CreatePrimitive(Enum.Primitive.Cube)
zone.transform.position = Vector3.New(0, 0, 5)
zone.transform.localScale = Vector3.New(5, 5, 5)
local trigger = Trigger.Add(zone)
Trigger.SetTag(trigger, "Player")
Trigger.OnEnter(trigger, function(other)
print("Player entered zone!")
Input.Vibrate(Enum.Hand.Right, 1.0, 0.2)
end)
Trigger.OnExit(trigger, function(other)
print("Player left zone!")
end)
Example: Physics Collision
-- Create a bouncing balllocal ball = GameObject.CreatePrimitive(Enum.Primitive.Sphere)
ball.transform.position = Vector3.New(0, 5, 0)
local collision = Collision.Add(ball)
Collision.OnEnter(collision, function(other)
print("Ball hit: " .. other.name)
Input.Vibrate(Enum.Hand.Right, 0.5, 0.1)
end)
Physics & Raycasting
Physics.Raycast(origin, direction, maxDistance)
Cast a ray and detect hits
origin - Vector3 starting point
direction - Vector3 direction (should be normalized)
maxDistance - Maximum ray distance
direction - Vector3 direction (should be normalized)
maxDistance - Maximum ray distance
Returns: table with {hit, point, normal, distance, collider, gameObject}
Physics.SphereCast(origin, radius, direction, maxDistance)
Cast a sphere and detect hits
Returns: table with {hit, point, normal, distance, gameObject}
Physics.OverlapSphere(position, radius)
Find all colliders within a sphere
Returns: Collider array
Example: Raycast from Controller
-- Cast a ray forward from right controllerlocal controllerPos = Input.RightControllerPosition()
local forward = Vector3.Forward()
local hit = Physics.Raycast(controllerPos, forward, 10)
if hit.hit then
print("Hit object: " .. hit.gameObject.name)
print("Distance: " .. hit.distance)
print("Hit point: " .. hit.point)
else
print("Nothing hit")
end
Example: Area Detection
-- Find all objects near playerlocal playerPos = Input.HeadsetPosition()
local nearby = Physics.OverlapSphere(playerPos, 5.0)
print("Found " .. #nearby .. " nearby objects")
for i, collider in ipairs(nearby) do
print("Object: " .. collider.gameObject.name)
end
Vectors & Math
Vector3
Vector3.New(x, y, z)
Create a new Vector3
Returns: Vector3
Vector3.Distance(a, b)
Calculate distance between two points
Returns: float
Vector3.Lerp(a, b, t)
Linear interpolation between two vectors
t - 0.0 to 1.0
Returns: Vector3
Vector3.Zero() / One() / Up() / Down() / Left() / Right() / Forward() / Back()
Static vector constants
Vector2
Vector2.New(x, y)
Create a new Vector2
Vector2.Distance(a, b)
Calculate distance between two 2D points
Vector2.Lerp(a, b, t)
Linear interpolation
Color
Color.New(r, g, b, a)
Create a color (values 0.0 to 1.0)
Color.Red() / Green() / Blue() / White() / Black() / Yellow() / Cyan() / Magenta()
Color presets
Random
Random.Range(min, max)
Random float between min and max
Random.RangeInt(min, max)
Random integer between min and max (exclusive)
Example: Vector Math
local pos1 = Vector3.New(0, 0, 0)local pos2 = Vector3.New(5, 0, 5)
local distance = Vector3.Distance(pos1, pos2)
print("Distance: " .. distance)
-- Interpolate between positions
local midpoint = Vector3.Lerp(pos1, pos2, 0.5)
print("Midpoint: " .. midpoint)
-- Random position
local randomPos = Vector3.New(
Random.Range(-10, 10),
Random.Range(0, 5),
Random.Range(-10, 10)
)
Time & Coroutines
Time.time()
Get time since game started
Returns: float (seconds)
Time.deltaTime()
Get time since last frame
Returns: float (seconds)
Time.timeScale()
Get current time scale
Time.SetTimeScale(scale)
Set game speed (1.0 = normal, 0.5 = half speed, 2.0 = double speed)
wait(seconds)
Pause execution for specified time (use in coroutines)
StartCoroutine(name, function)
Start a named coroutine (can be stopped later)
StopCoroutine(name)
Stop a running coroutine by name
Example: Coroutine Timer
StartCoroutine("countdown", function()for i = 5, 1, -1 do
print("Countdown: " .. i)
wait(1.0)
end
print("GO!")
end)
-- Stop it early if needed
-- StopCoroutine("countdown")
Example: Slow Motion
-- Activate slow motionTime.SetTimeScale(0.5)
-- After 3 seconds, return to normal
StartCoroutine("slowmo", function()
wait(3.0)
Time.SetTimeScale(1.0)
end)
Networking (Photon)
Multiplayer RPCs
The networking system uses Photon's RaiseEvent system. Each RPC needs a unique ID between 0-154.
RPC Management
EventManager.Register(name, id, callback)
Register a new RPC that can be called over the network
name - Unique RPC name
id - Unique ID (0-154)
callback - function(data) called when RPC is received
id - Unique ID (0-154)
callback - function(data) called when RPC is received
EventManager.Call(name, receivers, data)
Call an RPC across the network
name - RPC name to call
receivers - Enum.Receivers.All, Others, or MasterClient
data - Data to send (string, number, table, etc.)
receivers - Enum.Receivers.All, Others, or MasterClient
data - Data to send (string, number, table, etc.)
EventManager.GetAvailableId()
Get the next available RPC ID
Returns: integer (or -1 if all slots taken)
Game State
game.IsMasterClient()
Check if this client is the master client (host)
Returns: boolean
game.IsRunning()
Check if the game is running (not in editor)
Returns: boolean
Example: Simple Multiplayer System
-- Register an RPC for spawning objectsEventManager.Register("SpawnCube", 1, function(data)
local pos = Vector3.New(data.x, data.y, data.z)
local cube = GameObject.CreatePrimitive(Enum.Primitive.Cube)
cube.transform.position = pos
print("Cube spawned at: " .. pos)
end)
-- When A button pressed, spawn cube for everyone
if Input.AButtonDown() then
local spawnData = {
x = Random.Range(-5, 5),
y = 2,
z = Random.Range(-5, 5)
}
EventManager.Call("SpawnCube", Enum.Receivers.All, spawnData)
end
Example: Master Client Authority
-- Only master client can trigger eventsif game.IsMasterClient() then
EventManager.Register("GameStart", 2, function(data)
print("Game starting!")
end)
-- Start game for all players
if Input.YButtonDown() then
EventManager.Call("GameStart", Enum.Receivers.All, nil)
end
end
Audio
Audio Components
Audio sources can play sounds in 3D space with distance attenuation and spatial audio.
gameObject.AddComponent(AudioSource)
Add an audio source component to a GameObject
Returns: AudioSource
audioSource.Play()
Play the audio clip
audioSource.Stop()
Stop playing audio
audioSource.Pause()
Pause audio playback
audioSource.volume
Get or set volume (0.0 to 1.0)
audioSource.pitch
Get or set pitch (0.5 to 2.0, 1.0 is normal)
audioSource.loop
Get or set looping (boolean)
audioSource.spatialBlend
Get or set 2D/3D blend (0.0 = 2D, 1.0 = 3D)
Example: 3D Spatial Audio
-- Create a sound emitter in 3D spacelocal emitter = GameObject.New("SoundEmitter")
emitter.transform.position = Vector3.New(5, 1, 5)
local audio = emitter.AddComponent(AudioSource)
audio.volume = 0.8
audio.spatialBlend = 1.0 -- Full 3D audio
audio.loop = true
audio.Play()
Lighting
gameObject.AddComponent(Light)
Add a light component to a GameObject
Returns: Light
light.type
Light type: Enum.LightType.Spot, Point, Directional, or Area
light.color
Light color (Color)
light.intensity
Light brightness (float)
light.range
Light range for point and spot lights (float)
light.spotAngle
Spot light cone angle (0-180 degrees)
Example: Dynamic Lighting
-- Create a pulsing point lightlocal lightObj = GameObject.New("DynamicLight")
lightObj.transform.position = Vector3.New(0, 3, 0)
local light = lightObj.AddComponent(Light)
light.type = Enum.LightType.Point
light.color = Color.New(1.0, 0.5, 0.0) -- Orange
light.range = 10
-- Pulse the light
StartCoroutine("pulse", function()
while true do
for i = 0, 20 do
light.intensity = 1 + math.sin(Time.time() * 3)
wait(0.05)
end
end
end)
Example: Flashlight
-- Attach spotlight to controllerlocal flashlight = GameObject.New("Flashlight")
local light = flashlight.AddComponent(Light)
light.type = Enum.LightType.Spot
light.color = Color.White()
light.intensity = 2
light.range = 15
light.spotAngle = 45
-- Update position every frame
StartCoroutine("updateFlashlight", function()
while true do
flashlight.transform.position = Input.RightControllerPosition()
flashlight.transform.rotation = Input.RightControllerRotation()
wait(0)
end
end)
Particles
gameObject.AddComponent(ParticleSystem)
Add a particle system component
Returns: ParticleSystem
particleSystem.Play()
Start emitting particles
particleSystem.Stop()
Stop emitting particles
particleSystem.Pause()
Pause particle emission
particleSystem.Clear()
Remove all existing particles
Example: Particle Effects
-- Create explosion effectlocal explosion = GameObject.New("Explosion")
explosion.transform.position = Vector3.New(0, 1, 5)
local particles = explosion.AddComponent(ParticleSystem)
particles.Play()
-- Destroy after 2 seconds
StartCoroutine("cleanupExplosion", function()
wait(2.0)
GameObject.Destroy(explosion)
end)
Complete Examples
Example 1: VR Grab System
VR Object Grabbing
-- Track grabbed objectlocal grabbedObject = nil
local grabOffset = Vector3.Zero()
-- Check for grab each frame
StartCoroutine("grabUpdate", function()
while true do
local gripValue = Input.RightGrip()
if gripValue > 0.7 and grabbedObject == nil then
-- Cast ray from controller
local controllerPos = Input.RightControllerPosition()
local forward = Vector3.Forward()
local hit = Physics.Raycast(controllerPos, forward, 2)
if hit.hit then
grabbedObject = hit.gameObject
grabOffset = grabbedObject.transform.position - controllerPos
Input.Vibrate(Enum.Hand.Right, 0.3, 0.1)
end
elseif gripValue < 0.3 and grabbedObject ~= nil then
-- Release object
grabbedObject = nil
Input.Vibrate(Enum.Hand.Right, 0.2, 0.05)
end
-- Update grabbed object position
if grabbedObject ~= nil then
local controllerPos = Input.RightControllerPosition()
grabbedObject.transform.position = controllerPos + grabOffset
end
wait(0)
end
end)
Example 2: Target Shooting Gallery
Shooting Gallery with Score
local score = 0local targets = {}
-- Spawn targets
for i = 1, 5 do
local target = GameObject.CreatePrimitive(Enum.Primitive.Sphere)
target.transform.position = Vector3.New(
Random.Range(-5, 5),
Random.Range(1, 3),
10
)
target.transform.localScale = Vector3.New(0.5, 0.5, 0.5)
-- Make target red
local renderer = target.GetComponent(Renderer)
renderer.material.color = Color.Red()
table.insert(targets, target)
end
-- Shooting logic
StartCoroutine("shootingLoop", function()
while true do
if Input.RightTrigger() > 0.9 then
local pos = Input.RightControllerPosition()
local rot = Input.RightControllerRotation()
local forward = Vector3.Forward() -- Transform by rotation
local hit = Physics.Raycast(pos, forward, 50)
if hit.hit then
-- Check if we hit a target
for i, target in ipairs(targets) do
if target == hit.gameObject then
score = score + 1
print("Hit! Score: " .. score)
GameObject.Destroy(target)
table.remove(targets, i)
Input.Vibrate(Enum.Hand.Right, 1.0, 0.2)
break
end
end
end
wait(0.2) -- Fire rate delay
end
wait(0)
end
end)
Example 3: Multiplayer Spawner
Synchronized Object Spawning
-- Register RPC for spawningEventManager.Register("NetworkSpawn", 10, function(data)
local obj = GameObject.CreatePrimitive(data.type)
obj.transform.position = Vector3.New(data.x, data.y, data.z)
obj.transform.localScale = Vector3.New(data.scale, data.scale, data.scale)
local renderer = obj.GetComponent(Renderer)
renderer.material.color = Color.New(data.r, data.g, data.b)
end)
-- Spawn objects when button pressed
StartCoroutine("spawnLoop", function()
while true do
if Input.AButtonDown() then
local spawnData = {
type = Enum.Primitive.Cube,
x = Random.Range(-5, 5),
y = 5,
z = Random.Range(-5, 5),
scale = Random.Range(0.5, 2.0),
r = Random.Range(0, 1),
g = Random.Range(0, 1),
b = Random.Range(0, 1)
}
EventManager.Call("NetworkSpawn", Enum.Receivers.All, spawnData)
end
wait(0)
end
end)
Example 4: Teleportation System
VR Teleport Mechanic
local teleportMarker = GameObject.CreatePrimitive(Enum.Primitive.Cylinder)teleportMarker.transform.localScale = Vector3.New(1, 0.1, 1)
teleportMarker.SetActive(false)
local renderer = teleportMarker.GetComponent(Renderer)
renderer.material.color = Color.New(0, 1, 0, 0.5) -- Green transparent
local player = GameObject.Find("Player")
StartCoroutine("teleportSystem", function()
while true do
local stick = Input.LeftStick()
if stick.y > 0.8 then
-- Show teleport marker
local controllerPos = Input.LeftControllerPosition()
local forward = Vector3.Forward()
local hit = Physics.Raycast(controllerPos, forward, 10)
if hit.hit then
teleportMarker.SetActive(true)
teleportMarker.transform.position = hit.point
end
else
-- Teleport on release
if teleportMarker.activeSelf then
player.transform.position = teleportMarker.transform.position
teleportMarker.SetActive(false)
Input.Vibrate(Enum.Hand.Left, 0.5, 0.1)
end
end
wait(0)
end
end)