CI / quality (push) Successful in 54s
- 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
91 lines
3.7 KiB
Markdown
91 lines
3.7 KiB
Markdown
# 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:
|
||
1. **Buy or find a free RX-7 FD model** on the Roblox Creator Marketplace/toolbox,
|
||
or
|
||
2. **Model it** in Blender from the reference photos and import the mesh
|
||
(`.fbx`/`.obj`) via Studio's 3D importer, or
|
||
3. 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 `.rbxm` and reference it from the
|
||
Rojo project so it lives in git. See Rojo's `$path` docs for `.rbxm` model files.
|
||
|
||
## Step 3 — Attach the shell in `buildCarModel`
|
||
In `CarManager.buildCarModel`, after the Body part is created:
|
||
|
||
```lua
|
||
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.rbxl` compiles.
|
||
- 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).
|