My latest tutorial on character dashing!
I’ve seen the tutorial and it’s very good but is it possible to make a version without Promise module and maybe give the model so we can read the script easier ? Btw it’s a very good dash
You can. Promises act as wrappers around coroutines, offering more functionality. Particularly relevant to this tutorial is the ability to chain threads to execute in succession. The alternative is to return an event for completion, which would be fired when we reach target velo (pretty much just substitute promise resolves for event firings). This would be similar to tweens where you can subscribe to a .Completed event.
But I would recommend using promises here. Returning events in this context is quite repetitive, inflexible and awkward. Imagine each time you want to chain you have to create a new event. Here it’s as simple as just returning a promise. Having this uniform API makes it easier to cancel the promise chain and also to handle errors (I’m sure you can imagine an error scenario, perhaps we couldn’t complete the dash because the character wasn’t on the ground, etc.). See Promises and why you should use them.
As for providing a model, this is purposefully a community tutorial and not a resource. So the expectation is to go through the tutorial and take what you need!
The dash is laggy , like if i want to dash but in a wall my character will just fling…
mhmm, laggy is concerning, but if you only meant it flings the character when it hits a wall, then that is expected when using LinearVelocity in general. Imagine it’s trying to maintain some velocity while knocking against a wall every frame. For a solution, you can do a cast to see if it comes up against a wall and handle it appropriately from there.
See:
I know how to make dashing but still, you’re like the only dude who makes high quality video tutorials like the one on sliding. W
There’s a few ways to fix this problem
First, the linearvelocity’s maxforce, lower it to around 30000 for a player.
Second, a bodygyro, the reason for using the deprecated one is because it works differently and fits what you want
This is an example, of the bodygyro and the maxforce, the actual dash itself isn’t as clean as the tutorial one.
function Dash(Direction, Force, Duration)
if Character.HumanoidRootPart:FindFirstChild("VectorForce") then
Character.HumanoidRootPart:FindFirstChild("VectorForce"):Destroy()
end
local vectorForce = Instance.new("LinearVelocity")
local Torque = Instance.new("BodyGyro")
Torque.Parent = Character.HumanoidRootPart
Torque.MaxTorque = Vector3.new(math.huge,math.huge,math.huge)
vectorForce.Parent = Character.HumanoidRootPart
vectorForce.Attachment0 = Character.HumanoidRootPart.RootAttachment
vectorForce.VelocityConstraintMode = Enum.VelocityConstraintMode.Line
vectorForce.RelativeTo = Enum.ActuatorRelativeTo.World
vectorForce.MaxForce = 30000
vectorForce.LineDirection = Character.HumanoidRootPart.CFrame[Direction]
vectorForce.LineVelocity = (Force)
game.Debris:AddItem(Torque,Duration+0.15)
game.Debris:AddItem(vectorForce,Duration)
end
Dash("LookVector",45,0.3)
also one of the most important parts
Character.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Ragdoll, false)
Character.Humanoid:SetStateEnabled(Enum.HumanoidStateType.FallingDown, false)
Hey, i tried using your physics logic to make a dash system but my character only goes around 5-10 studs, can i get some help, thanks!
module
u = intial velocity
v = final velocity
dt/t = time
s = distance
a = acceleration
]]
-- // Services
local runservice = game:GetService("RunService")
-- // Modules
local module = {}
local Promise = require(script.Parent.Promise)
-- // Functions
function AccelerateLinear(lv:LinearVelocity,targetvelocity:Vector2,acceleration)
local currentvelocity : Vector2 = lv.PlaneVelocity
local deltaV : Vector2 = targetvelocity - currentvelocity -- Change in velocity
local _,dt = runservice.Stepped:Wait() -- gotta change vecloity before frame renders
local newaccel = deltaV/dt -- accelration required to reach target velocity in time
local finalaccel = (newaccel.Magnitude < acceleration) and newaccel or newaccel.Unit * acceleration -- acceleration we will use
return Promise.new(function(resolve,reject)
local connection : RBXScriptConnection
local frame_left = 1 -- how many frame left before we stop connection
connection = runservice.Stepped:Connect(function(time,dt)
-- Updating the velocity
lv.PlaneVelocity += finalaccel * dt -- We add the velocity we supposed to add in 1 frame, v - u = a*t(u is 0 here)
if (targetvelocity - lv.PlaneVelocity).Magnitude <= finalaccel.Magnitude * dt * frame_left then
lv.PlaneVelocity = targetvelocity
connection:Disconnect()
resolve()
end
end)
end)
end
function module:AccelerateDistanceLinear(targetvelocity:Vector2,acceleration_time,s,hrp)
local atc = Instance.new("Attachment")
atc.Parent = hrp
local lv = Instance.new("LinearVelocity")
lv.MaxForce = math.huge
lv.VelocityConstraintMode = Enum.VelocityConstraintMode.Plane
lv.PlaneVelocity = Vector2.zero
lv.Attachment0 = atc
lv.RelativeTo = Enum.ActuatorRelativeTo.World
lv.PrimaryTangentAxis = Vector3.xAxis
lv.SecondaryTangentAxis = Vector3.zAxis
lv.Parent = hrp
local s_travelled = 0.5 * (targetvelocity.Magnitude) * acceleration_time -- s = 1/2 * at^2, a = v-u/t, u = 0
local s_left = s - s_travelled
local negative_acceleration = math.abs(-(targetvelocity.Magnitude^2)/2*s_left) -- v^2 - u^2 = 2as
return AccelerateLinear(lv,targetvelocity,targetvelocity.Magnitude/acceleration_time):andThen(function()
return AccelerateLinear(lv,Vector2.zero,negative_acceleration):andThen(function()
atc:Destroy()
lv:Destroy()
end)
end)
end
return module
local script module
local targetvelocity = 60
local dashdistance = 18
local direction = {
ForwardDash = Vector3.new(0,0,1),
BackDash = Vector3.new(0,0,-1),
LeftDas =Vector3.new(-1,0,0),
RightDash = Vector3.new(1,0,0),
}
-- // Functions
function module:Dash(plr:Player,humanoid:Humanoid,hrp)
if candash then
candash = false
local movedirection = (humanoid.MoveDirection * Vector3.new(1,0,1)).Unit
local animation = "ForwardDash"
if humanoid.MoveDirection == Vector3.zero then
movedirection= (hrp.CFrame.LookVector * Vector3.new(1,0,1)).Unit
animation = "ForwardDash"
elseif uis.MouseBehavior == Enum.MouseBehavior.LockCenter then
local closest = math.huge
for name,velocity in pairs(direction) do
local difference = 1 - (hrp.CFrame * velocity):Dot(humanoid.MoveDirection)
if difference < closest then
closest = difference
animation = name
end
end
end
print(direction)
return Promise.new(function(resolve)
animationhandler:Playanimation(plr.Character,animation)
physicsstimulator:AccelerateDistanceLinear(targetvelocity * Vector2.new(movedirection.X,movedirection.Z).Unit,0.01,dashdistance,hrp)
resolve()
end):andThen(function()
candash = true
end)
end
end```
That is strange. The only thing I see wrong perhaps is the debounce logic for canDash, since this promise will resolve immediately (assuming Playanimation doesn’t yield and just plays). You’d need to either wait on animation to end, AccelerateDistanceLinear to finish, or whichever one takes longer using Promise.all, then resolve.
Otherwise, if you don’t press the dash key while it’s already active (debounce logic wouldn’t matter in that case) then it should travel the correct distance. I could be overlooking a small detail, but as of right now my eyes don’t see anything wrong.
Thanks for this answer actually, this is the best and simplest way of going about it. If one wants to be methodical about how they set MaxForce exactly, the following code should work, it’s based on the maximum acceleration the hrp (or whatever you’re accelerating) will possibly experience.
LV.MaxForce = ((targetVelocity.Magnitude/accTime) * hrp.AssemblyMass) + 250
250 is arbitrary legroom, this way the force output to reach target velocity is capped and the physics engine doesn’t go beyond it in trying to maintain velocity going against an immovable object.
Hey the dash works well but do you know how I could implement like the direction of the dash update every frames ?
Carried out discussion offline. Turns out OP had to rewrite (targetvelocity.Magnitude^2)/2*s_left
as
(targetvelocity.Magnitude^2)/(2*s_left)
. Division and multiplication are of the same precedence (Programming in Lua : 3.5) so associativity takes over evaluating from left to right, unless we surround multiplication with parentheses.
I watched the video and finished the script ,but i really didnt know how to make the animation .So ,my character couldnt walk ,instead of playing the animation in a fixed place