Sistem Humanoid standar Roblox sering mengalami kendala pada game aksi: gerakan terasa lamban, tersendat di tangga, dan mudah terlempar saat berada di atas platform bergerak.
Dengan membuat kontroler kustom berbasis fisika, pengembang dapat menghadirkan kendali penuh. Memanfaatkan suspensi kapsul VectorForce dan proyeksi vektor lereng via raycast, gerakan karakter menjadi sangat responsif layaknya game aksi kelas atas.
1. Keterbatasan Humanoid Bawaan pada Game Cepat
Alasan game kompetitif membutuhkan sistem kontroler mandiri:
- State Machine Kaku: Pergantian animasi lambat menghambat respons manuver.
- Terlempar di Kendaraan: Desinkronisasi fisika pada pijakan bergerak yang melontarkan karakter.
- Guncangan di Tangga: Lonjakan vertikal mendadak yang merusak kehalusan kamera.
- Kendali Deterministik: Menghitung kecepatan secara matematis di setiap Heartbeat.
2. Kapsul Melayang dan Suspensi Pegas VectorForce
Melayang tanpa kontak langsung agar gerakan selalu mulus di berbagai permukaan:
- Suspensi Virtual: Raycast ke bawah memberikan gaya pegas yang menahan karakter melayang stabil.
- Kapsul Nol Gesekan: Selubung luar licin mencegah karakter tersangkut di celah sempit.
- Stabilisasi AlignOrientation: Menjaga karakter tetap berdiri tegak tanpa gulingan yang tak diinginkan.
- Respons LinearVelocity: Mencapai kecepatan target seketika tanpa jeda akselerasi lambat.
--!strict
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local Workspace = game:GetService("Workspace")
local Players = game:GetService("Players")
local CustomController = {}
local player = Players.LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local hrp = char:WaitForChild("HumanoidRootPart") :: BasePart
local TARGET_HEIGHT = 4.2
local SPRING_STIFFNESS = 1800
local SPRING_DAMPING = 160
local WALK_SPEED = 24
local RAY_PARAMS = RaycastParams.new()
RAY_PARAMS.FilterType = RaycastFilterType.Exclude
local linearVelocity = Instance.new("LinearVelocity")
linearVelocity.MaxForce = 40000
linearVelocity.VelocityConstraintMode = Enum.VelocityConstraintMode.Vector
linearVelocity.RelativeTo = Enum.ActuatorRelativeTo.World
local attachment = Instance.new("Attachment")
attachment.Parent = hrp
linearVelocity.Attachment0 = attachment
linearVelocity.Parent = hrp
function CustomController.Update(dt: number)
local moveDir = Vector3.zero
local cam = Workspace.CurrentCamera
if UserInputService:IsKeyDown(Enum.KeyCode.W) then moveDir += cam.CFrame.LookVector end
if UserInputService:IsKeyDown(Enum.KeyCode.S) then moveDir -= cam.CFrame.LookVector end
if UserInputService:IsKeyDown(Enum.KeyCode.D) then moveDir += cam.CFrame.RightVector end
if UserInputService:IsKeyDown(Enum.KeyCode.A) then moveDir -= cam.CFrame.RightVector end
moveDir = Vector3.new(moveDir.X, 0, moveDir.Z)
if moveDir.Magnitude > 0.01 then moveDir = moveDir.Unit end
RAY_PARAMS.FilterDescendantsInstances = { char }
local ray = Workspace:Raycast(hrp.Position, Vector3.new(0, -TARGET_HEIGHT * 1.5, 0), RAY_PARAMS)
local vForce = 0
local targetVel = moveDir * WALK_SPEED
if ray and ray.Instance and ray.Instance.CanCollide then
local dist = (hrp.Position - ray.Position).Magnitude
targetVel = moveDir - (ray.Normal * moveDir:Dot(ray.Normal))
targetVel = targetVel.Unit * WALK_SPEED
local err = TARGET_HEIGHT - dist
vForce = (err * SPRING_STIFFNESS) - (hrp.AssemblyLinearVelocity.Y * SPRING_DAMPING)
end
linearVelocity.VectorVelocity = Vector3.new(targetVel.X, targetVel.Y + (vForce * dt), targetVel.Z)
end
RunService.Heartbeat:Connect(CustomController.Update)
return CustomController
3. Deteksi Tanah Raycast dan Proyeksi Vektor Lereng
Menjaga kelajuan konstan saat mendaki maupun menuruni bukit:
- Vektor Normal Permukaan: Menentukan kemiringan bidang tanah secara presisi.
- Proyeksi Gerakan: Membelokkan arah jalan sejajar dengan sudut kemiringan bukit.
- Batas Sudut Daki: Meluncur otomatis saat menghadapi tebing di atas 45 derajat.
- Deteksi Tepi Jurang: Sinar bantu untuk mendeteksi tepi jurang sebelum terjatuh.
4. Inersia Momentum dan Mekanika Sliding Dinamis
Menghadirkan manuver parkour dan seluncuran yang memuaskan:
- Luncuran Jongkok: Mengurangi gesekan saat menekan tombol jongkok saat berlari.
- Dorongan Menuruni Bukit: Bonus kecepatan gravitasi saat berseluncur di turunan.
- Penyimpanan Momentum: Kecepatan tidak langsung hilang saat selesai berseluncur.
- Kendali di Udara: Memungkinkan manuver saat melompat tanpa menghasilkan kecepatan tanpa batas.
5. Sinkronisasi Animasi Prosedural & Penjejakan Kaki
Menyelaraskan kecepatan fisik dengan gerakan animasi kerangka 3D:
- Mencegah Kaki Terseret: Mengatur tempo animasi sebanding dengan kecepatan gerak asli.
- Pencampuran 8 Arah: Transisi halus sesuai arah pergerakan.
- Penempatan Kaki IKControl: Kaki menapak sempurna di permukaan bertangga.
- Pemrosesan di Klien: Mengurangi beban server dengan memproses fisika secara lokal.
Frequently Asked Questions
Mengapa kapsul harus dibuat melayang di atas tanah?
Kontak langsung membuat karakter mudah tersandung celah kecil; suspensi melayang menjamin kelancaran melangkah.
Bagaimana proyeksi lereng mencegah pengurangan kecepatan saat mendaki?
Dengan mengarahkan gaya dorong sejajar lereng bukit sehingga tidak tertahan oleh bidang miring.
Apakah ini mencegah bug terlempar dari platform bergerak?
Ya, karena kontroler dapat secara langsung menyelaraskan kecepatan dengan pijakan di bawahnya.