Physics Mod is a custom sandbox game inspired by Garry's Mod, but made to feel easier, faster, and more flexible to create with. Mess with physics, make your own scripts, build custom mods, and prototype cool ideas without fighting the engine.
Put your game build, launcher, GitHub, itch.io page, or patch downloads here.
This section is ready for your real links. Replace the buttons below with your latest build, older builds, changelog, Discord, or wherever you host Physics Mod.
Physics Mod is built around freedom, fast iteration, and making sandbox content without loads of setup.
Built in C# with Raylib instead of relying on a giant engine, so the game can grow its own systems, tools, and workflow.
Use simple Lua hooks and helper functions to make menus, tools, chat features, player tweaks, and gameplay ideas quickly.
Spawn things, test ideas, mess with physics, and create fun scenes like a proper sandbox should let you.
The goal is to make content creation simpler, so adding your own stuff feels fun instead of annoying.
Quick reference for Physics Mod Lua. This includes lifecycle hooks, API groups, button hook behavior, ADS helpers, and ready-to-copy examples.
init()update(dt)on_chat(playerName, text)game.get_mod_name()game.get_mod_folder()game.get_mod_root()game.get_player_name()game.get_time()game.get_player_count()game.is_multiplayer()game.is_host()game.is_client()game.set_status(text)game.print(text)chat.say(text)input.key_down("q")input.key_pressed("q")input.key_released("q")input.mouse_down("left")input.mouse_pressed("left")input.mouse_released("left")input.mouse_x()input.mouse_y()input.set_cursor_visible(true)input.is_cursor_visible()input.screen_width()input.screen_height()player.get_x()player.get_y()player.get_z()player.teleport(x, y, z)player.set_position(x, y, z)player.get_yaw()player.get_pitch()player.set_view(yawDegrees, pitchDegrees)player.get_move_speed()player.set_move_speed(value)player.get_sprint_multiplier()player.set_sprint_multiplier(value)player.get_jump_force()player.set_jump_force(value)player.get_gravity()player.set_gravity(value)weapons.get_active()weapons.select(name)weapons.reload()weapons.set_reserve_ammo(name, value)weapons.add_reserve_ammo(name, amount)weapons.set_magazine_ammo(name, value)weapons.add_magazine_ammo(name, amount)Put AdsOffsetX / AdsOffsetY / AdsOffsetZ in weapon.json for per-weapon ADS positionweapons.set_ads_pose(x, y, z, rotX, rotY, rotZ, speed)weapons.set_ads_position(x, y, z, speed)weapons.set_ads_rotation(x, y, z, speed)weapons.set_ads_active(true)weapons.is_ads_active()weapons.get_ads_blend()weapons.clear_ads()hud.text(x, y, text, fontSize, color, centered)hud.panel(x, y, width, height, color, borderColor)hud.button(x, y, width, height, text, hook, fontSize, color, hoverColor, borderColor, textColor)hud.screen_width()hud.screen_height()hud.set_cursor_visible(true)hud.is_cursor_visible()ui is an alias of hudhook can be a function name string like "my_hook"my_hookui.button(...) returns true on the frame it was clickedThis flips a boolean when you press Q and shows or hides the cursor.
local menu_open = false
function update(dt)
if input.key_pressed("q") then
menu_open = not menu_open
input.set_cursor_visible(menu_open)
end
end
This puts a button on screen, and clicking it sends a hello message into chat.
function say_hello()
chat.say("Hello from button")
end
function update(dt)
if input.key_pressed("q") then
input.set_cursor_visible(true)
end
hud.button(40, 120, 180, 42, "Say Hello", "say_hello", 20, "#3A5DAE", "#5B7DD4", "#FFFFFF40", "#FFFFFF")
end
This turns aim-down-sights on only while the right mouse button is being held.
function update(dt)
weapons.set_ads_active(input.mouse_down("right"))
end
This prints useful basic info when the script starts.
function init()
game.print("Mod: " .. game.get_mod_name())
game.print("Folder: " .. game.get_mod_folder())
game.print("Player: " .. game.get_player_name())
game.print("Players online: " .. game.get_player_count())
end
This moves the player to a set spot when E is pressed.
function update(dt)
if input.key_pressed("e") then
player.teleport(0, 10, 0)
game.print("Teleported")
end
end
This sets custom movement values when the mod loads.
function init()
player.set_move_speed(7)
player.set_sprint_multiplier(1.8)
player.set_jump_force(8)
player.set_gravity(18)
game.print("Movement updated")
end
This draws the player's current X, Y, and Z on screen every frame.
function update(dt)
local x = player.get_x()
local y = player.get_y()
local z = player.get_z()
hud.panel(20, 20, 260, 80, "#101722CC", "#8FB4FF40")
hud.text(30, 32, "Position", 20, "#FFFFFF", false)
hud.text(30, 60, "X: " .. x .. " Y: " .. y .. " Z: " .. z, 16, "#CFE0FF", false)
end
This applies a custom ADS position and rotation while holding right click.
function update(dt)
if input.mouse_down("right") then
weapons.set_ads_pose(-0.08, -0.04, 0.12, 0, 0, 0, 10)
weapons.set_ads_active(true)
else
weapons.clear_ads()
end
end
This shows that button hooks can use the function itself instead of a string name.
function open_chat_message()
chat.say("Direct function hook worked")
end
function update(dt)
ui.button(40, 180, 240, 42, "Direct Hook Button", open_chat_message, 20, "#3A5DAE", "#5B7DD4", "#FFFFFF40", "#FFFFFF")
end
This uses the return value from ui.button(...) and prints when it was clicked.
function update(dt)
local clicked = ui.button(40, 240, 220, 42, "Click Me", nil, 20, "#3A5DAE", "#5B7DD4", "#FFFFFF40", "#FFFFFF")
if clicked then
game.print("Button was clicked this frame")
end
end