I’m currently making a quake movement or bhop system from this article for my game and I’m trying to find what exactly the acceleratedDirection
is. My first attempt that acceleratedDirection
would be Humanoid.MoveDirection
but the result is inaccurate which I didn’t move my camera:
Here’s my code:
--!strict
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
type Controls = {
GetMoveVector: (self: Controls) -> Vector3,
}
type PlayerModule = {
GetControls: (self: PlayerModule) -> Controls,
}
local LocalPlayer = Players.LocalPlayer
local PlayerScripts = LocalPlayer:WaitForChild("PlayerScripts") :: PlayerScripts
local PlayerModule: PlayerModule =
require(PlayerScripts:WaitForChild("PlayerModule")) :: any
local MAX_VELOCITY_GROUND = 1000
local MAX_VELOCITY_AIR = 1000
local GROUND_ACCELERATE = 10
local AIR_ACCELERATE = 32
local FRICTION = 5
local function findChild<T>(
parent: Instance,
name: string,
predicate: (child: Instance) -> T
): T?
for _, child in ipairs(parent:GetChildren()) do
if child.Name ~= name then
continue
end
local result = predicate(child)
if result then
return result
end
end
return nil
end
local parent: Instance? = script.Parent
if not parent then
error(string.format("%s script has no parent!", script.Name))
end
local character = if parent:IsA("Model") then parent else nil
if not character then
error(string.format("Parent of %s must be a Model!", script.Name))
end
local humanoid = character:FindFirstChildOfClass("Humanoid")
if not humanoid then
error(
string.format(
"No Humanoid found for the %s script to use!",
script.Name
)
)
end
local rootPart = humanoid.RootPart
if not rootPart then
error(
string.format(
"No RootPart found for the %s script to use!",
script.Name
)
)
end
local rootAttachment = findChild(rootPart, "RootAttachment", function(child)
return if child:IsA("Attachment") then child else nil
end)
if not rootAttachment then
error(
string.format(
"No RootAttachment found for the %s script to use!",
script.Name
)
)
end
local function accelerate(
acceleratedDirection: Vector3,
previousVelocity: Vector3,
acceleration: number,
maxVelocity: number,
deltaTime: number
): Vector3
local projectionVelocity = previousVelocity:Dot(acceleratedDirection)
local acceleratedVelocity = acceleration * deltaTime
if projectionVelocity + acceleratedVelocity > maxVelocity then
acceleratedVelocity = maxVelocity - projectionVelocity
end
return previousVelocity + acceleratedDirection * acceleratedVelocity
end
local function moveGround(
acceleratedDirection: Vector3,
previousVelocity: Vector3,
deltaTime: number
): Vector3
local speed = previousVelocity.Magnitude
if speed ~= 0 then
local drop = speed * FRICTION * deltaTime
previousVelocity *= math.max(speed - drop, 0) / speed
end
return accelerate(
acceleratedDirection,
previousVelocity,
GROUND_ACCELERATE,
MAX_VELOCITY_GROUND,
deltaTime
)
end
local function moveAir(
acceleratedDirection: Vector3,
previousVelocity: Vector3,
deltaTime: number
): Vector3
return accelerate(
acceleratedDirection,
previousVelocity,
AIR_ACCELERATE,
MAX_VELOCITY_AIR,
deltaTime
)
end
local previousVelocity = Vector3.zero
RunService.Stepped:Connect(function(_, deltaTime)
local camera = workspace.CurrentCamera
local currentVelocity = Vector3.zero
local moveVector = PlayerModule:GetControls():GetMoveVector()
local moveDirection = camera
:GetRenderCFrame()
:VectorToWorldSpace(moveVector) * Vector3.new(1, 0, 1)
if humanoid.FloorMaterial ~= Enum.Material.Air and not humanoid.Jump then
currentVelocity = moveGround(moveDirection, previousVelocity, deltaTime)
else
currentVelocity = moveAir(moveDirection, previousVelocity, deltaTime)
end
previousVelocity = currentVelocity
rootPart.AssemblyLinearVelocity = Vector3.new(
currentVelocity.X,
rootPart.AssemblyLinearVelocity.Y,
currentVelocity.Z
)
end)