- New shared Chassis.luau: geometry constants + per-car tuning from stats - CarManager.buildCarModel rebuilt: prismatic+spring suspension per corner, servo-hinge steering on front knuckles, motor-hinge driven wheels, hidden dense ballast for anti-roll; VehicleSeat kept as input device only - New client ChassisController: drives motors/servos from seat ThrottleFloat/SteerFloat per Heartbeat; speed-sensitive steering lock; engine braking on throttle release - Driver gets network ownership of every unanchored part (constraint assemblies are separate; missing one causes stuttery physics) - Docs: MESH_SWAP.md rewritten for shell-on-chassis workflow; ROADMAP updated
3.7 KiB
Swapping the placeholder RX-7 for the real mesh (M1)
The car is now a constraint chassis (springs + steering servos + motor-driven
wheels — see src/shared/Chassis.luau and CarManager.buildCarModel). The
placeholder Body/Cabin blocks are just the visual shell riding on that chassis.
Making the RX-7 real means replacing the shell, not the chassis: weld a
MeshPart body onto the Body part and hide the placeholder blocks.
Nothing else (saving, the allowlist, car switching, driving feel, the map, anti-cheat) needs to change.
Reference photos
The real car's reference photos live on the NAS (too large to commit to git):
unraid-1:/mnt/user/data/yy-roblox-games/0-fast-n-furious-sim/001-1993 Mazda RX-7/
A single downscaled reference is included at assets/reference/rx7-reference.png
for quick lookups.
Step 1 — Get a mesh into Roblox
Options, easiest first:
- Buy or find a free RX-7 FD model on the Roblox Creator Marketplace/toolbox, or
- Model it in Blender from the reference photos and import the mesh
(
.fbx/.obj) via Studio's 3D importer, or - Commission one.
You want the car body shell as a single MeshPart (or a small welded Model with a clear root). Wheels can be separate meshes (see Step 4). Keep the part count low (mobile perf). This step needs Studio — mesh assets upload through Roblox's asset pipeline.
Step 2 — Store it where the server can clone it
Put the shell under ReplicatedStorage/CarModels/<carId> (e.g.
CarModels/rx7_fc). Two ways to manage it:
- Simple: keep it in the Studio place file as a real Instance (not synced by Rojo). Fine for a single hero car.
- Version-controlled: export the model to a
.rbxmand reference it from the Rojo project so it lives in git. See Rojo's$pathdocs for.rbxmmodel files.
Step 3 — Attach the shell in buildCarModel
In CarManager.buildCarModel, after the Body part is created:
local CAR_MODELS = ReplicatedStorage:FindFirstChild("CarModels")
-- inside buildCarModel, after `body` exists:
local shellTemplate = CAR_MODELS and CAR_MODELS:FindFirstChild(car.Id)
if shellTemplate then
local shell = shellTemplate:Clone()
-- Position the shell over the body, then weld it on.
shell:PivotTo(body.CFrame * CFrame.new(0, SHELL_Y_OFFSET, 0))
for _, p in ipairs(shell:GetDescendants()) do
if p:IsA("BasePart") then
p.CanCollide = false -- the Body part remains the collider
p.Anchored = false
end
end
local weld = Instance.new("WeldConstraint")
weld.Part0 = body
weld.Part1 = shell.PrimaryPart or shell:FindFirstChildWhichIsA("BasePart")
weld.Parent = body
shell.Parent = model
-- Hide the placeholder blocks:
body.Transparency = 1
local cabin = model:FindFirstChild("Cabin")
if cabin then cabin:Destroy() end
end
Cars without a mesh keep the block look automatically — import one car at a time.
Step 4 (polish) — Real wheel meshes
The chassis wheels are plain cylinders (Wheel_FL … Wheel_RR). To make them
look real, weld a wheel MeshPart (CanCollide=false) onto each cylinder and set
the cylinder's Transparency = 1. The cylinder stays the physics tyre — mesh
collision on wheels is unreliable and slow.
Sizing gotcha
The chassis geometry (Chassis.BODY_SIZE, WHEEL_RADIUS, TRACK_HALF,
WHEELBASE_HALF) is tuned for a ~6×12 stud footprint. Scale the imported mesh
to fit the chassis — don't reshape the chassis around the mesh, or the driving
feel changes for every car.
Verify
rojo build --output build.rbxlcompiles.- In Studio: Play → you spawn in the real RX-7 → it drives → it saves.
- Non-allowlisted test account still can't select the RX-7 (server enforced).