Wall running, berseluncur, dan memanjat tepian memberi sensasi aksi yang luar biasa dalam game modern. Mencoba membuatnya hanya dengan status Humanoid bawaan sering kali memicu tabrakan kaku dan jatuh mendadak.
Menggabungkan batasan fisika Luau (`LinearVelocity` dan `VectorForce`) dengan deteksi Raycast memungkinkan Anda membangun sistem parkour sekelas game konsol di semua perangkat.
1. Mengatur Ulang Status Humanoid untuk Parkour Mulus
Prinsip state machine pergerakan kustom:
- Matikan Status yang Berkonflik: Saat wall run dimulai, segera nonaktifkan memanjat dan jatuh bebas agar animasi bawaan tidak merusak fisika.
- Kepemilikan Jaringan (Network Ownership): Berikan kepemilikan RootPart ke pemain di server untuk meniadakan lag input.
- State Machine Modular: Pisahkan pergerakan ke dalam status Berjalan, Lari Cepat, WallRun, Bergantung, dan Memanjat.
2. Raycast Arah dan Penyelarasan Vektor Normal Dinding
Mendeteksi permukaan dinding dan arah pergerakan:
- Sonde Raycast Ganda: Tembakkan sinar horizontal dari pinggul dan bahu ke samping (3.5 stud) untuk mendeteksi dinding.
- Evaluasi Sudut Normal: Pastikan permukaan tegak lurus terhadap lantai (sudut 75° hingga 105°) agar tidak berlari di tanjakan landai.
- Vektor Arah dengan Cross Product: Hitung arah maju sejajar dinding menggunakan rumus
wallNormal:Cross(Vector3.yAxis).
3. Batasan Fisika Modern: LinearVelocity & VectorForce
Menggantikan BodyMovers lama dengan constraint modern:
- LinearVelocity untuk Kecepatan Stabil: Mempertahankan dorongan maju konstan tanpa melambat akibat gesekan dinding.
- VectorForce Antigravitasi: Meniadakan gravitasi bawaan (196.2 studs/s²) dengan gaya ke atas sesuai massa karakter.
- Penurunan Gaya Bertahap: Kurangi gaya ke atas setelah 1.5–2 detik untuk menciptakan lengkungan jatuh yang realistis.
-- Pengontrol Wall Running Klien
local RunService = game:GetService("RunService")
local WallRun = {}
WallRun.__index = WallRun
function WallRun.new(character)
local self = setmetatable({}, WallRun)
self.Char = character
self.RootPart = character:WaitForChild("HumanoidRootPart")
self.Humanoid = character:WaitForChild("Humanoid")
local att = Instance.new("Attachment", self.RootPart)
local lv = Instance.new("LinearVelocity")
lv.Attachment0 = att
lv.MaxForce = 15000
lv.RelativeTo = Enum.ActuatorRelativeTo.World
lv.Enabled = false
lv.Parent = self.RootPart
self.Attachment = att
self.LinearVelocity = lv
self.IsRunning = false
return self
end
function WallRun:CheckWall(side)
local rightVec = self.RootPart.CFrame.RightVector
local rayDir = (side == "Left" and -rightVec or rightVec) * 3.5
local params = RaycastParams.new()
params.FilterDescendantsInstances = {self.Char}
params.FilterType = Enum.RaycastFilterType.Exclude
return workspace:Raycast(self.RootPart.Position, rayDir, params)
end
function WallRun:Start(hitNormal, forwardDir)
self.IsRunning = true
self.LinearVelocity.VectorVelocity = forwardDir * 32 + Vector3.new(0, 4, 0)
self.LinearVelocity.Enabled = true
self.Humanoid:ChangeState(Enum.HumanoidStateType.Physics)
end
function WallRun:Stop()
self.IsRunning = false
self.LinearVelocity.Enabled = false
self.Humanoid:ChangeState(Enum.HumanoidStateType.Freefall)
end
return WallRun
4. Deteksi Tepian dan Gerakan Naik (Mantle)
Meraih bibir tebing dan transisi naik yang mulus:
- Raycast Dua Tahap: Sinar dada horizontal memastikan dinding, dan sinar vertikal dari atas mendeteksi ketinggian bibir tepian.
- Kunci Posisi dengan AlignPosition: Kunci RootPart di bibir tebing agar pemain dapat bergantung dengan stabil.
- Kurva Naik Bezier: Saat tombol lompat ditekan, naikkan RootPart dalam lengkungan halus melewati rintangan.
5. Kontrol Layar Sentuh & Validasi Server
Aksesibilitas mobile dan keamanan anti-cheat:
- Tombol Layar Sentuh Luas: Petakan lompatan dinding ke tombol layar sentuh minimal berukuran 48x48 piksel.
- Batas Kecepatan Server: Server memverifikasi jarak tempuh per frame untuk mencegah cheat terbang atau teleportasi.
- Verifikasi Keberadaan Dinding: Server menembakkan raycast sendiri untuk memastikan ada dinding nyata di dekat pemain.
Frequently Asked Questions
Mengapa harus menggunakan LinearVelocity daripada BodyVelocity?
BodyVelocity sudah usang. LinearVelocity adalah bagian dari mesin constraint baru Roblox yang lebih stabil dan menghitung massa secara akurat.
Bagaimana agar pemain tidak merosot ke bawah saat wall running?
Berikan gaya ke atas melalui VectorForce yang menyeimbangkan gravitasi ruang kerja selama beberapa detik.
Bagaimana cara menghitung vektor dorongan di sepanjang dinding?
Gunakan perkalian silang (Cross Product) antara vektor normal dinding hasil raycast dan vektor atas dunia (0, 1, 0).
Bagaimana server mencegah cheat terbang saat wall run?
Server memverifikasi keberadaan dinding secara independen dan membatasi kecepatan gerak maksimal karakter.