I am currently having a issue with LinearVelocity. Keep in mind there are multiple LinearVelocity objects being created by a hitbox to force away a player/dummy from the player’s position by the direction the attack is in.
Code
ALL CODE IS RUNNING ON THE SERVER
Legend:
Info: Info
is a configuration value that stores attributes.
Attacked_Direction: An attribute value set by a separate module to display the attack’s position from hitting the dummy/player.
AmountOfDamageDealt: The amount of damage the player/dummy has received from one attack for calculating force.
Force Module
local VectorForce: LinearVelocity = {}
VectorForce.VelocityConstraintMode = Enum.VelocityConstraintMode.Vector
VectorForce.ForceLimitsEnabled = true
VectorForce.ForceLimitMode = Enum.ForceLimitMode.PerAxis
VectorForce.RelativeTo = Enum.ActuatorRelativeTo.Attachment0
--VectorForce.ApplyAtCenterOfMass = true
--VectorForce.RelativeTo = Enum.ActuatorRelativeTo.Attachment0
local module = {}
--Current Force is defective btw
function module.CreateForce(instance: Instance, HumanoidRootPart, Direction: Vector3, AmountOfForce: number, Linger: number, MassScaling --[[, VectorForceVector3Force: Vector3]])
if HumanoidRootPart == nil then print("NO VALID HUMANOIDROOTPART, RETURNING") return end
if HumanoidRootPart.Anchored == true then return end
local Info = instance:FindFirstChild("Info")
if Info == nil then return end
local Immunities = Info:FindFirstChild("Immunities")
if Immunities == nil then return end
if Immunities:GetAttribute("KnockbackImmunity") == true then return end
--task.synchronize()
warn(Direction)
warn(AmountOfForce)
warn(HumanoidRootPart.Mass * MassScaling * AmountOfForce)
warn(Direction * (HumanoidRootPart.Mass * MassScaling) * AmountOfForce)
local Attachment0 = Instance.new("Attachment")
Attachment0.Parent = HumanoidRootPart
local VectorForceClone: LinearVelocity = Instance.new("LinearVelocity")
for PropertyName, Value in pairs (VectorForce) do
VectorForceClone[PropertyName] = Value
end
VectorForceClone.Attachment0 = Attachment0
local Formula = HumanoidRootPart.Mass * MassScaling
local ActualFormula = (Direction * Formula * AmountOfForce)
VectorForce.MaxAxesForce = Vector3.new(1,1,1) * math.huge
VectorForce.VectorVelocity = ActualFormula
VectorForceClone.Parent = HumanoidRootPart
--HumanoidRootPart.AssemblyLinearVelocity = VectorForceVector3Force
Debris:AddItem(VectorForceClone,Linger)
Debris:AddItem(Attachment0,Linger)
--task.delay(0.5,function()
-- HumanoidRootPart.AssemblyLinearVelocity = Vector3.new(0,0,0)
--end)
--task.desynchronize()
end
Stun System
Normal Knockback
DeathConnection = Humanoid:GetPropertyChangedSignal("Health"):Connect(function()
if Humanoid.Health <= 0 then
DeathConnection:Disconnect()
StunConnection:Disconnect()
elseif Humanoid.Health > 0 then
if Humanoid.Health > PreviousHealth then PreviousHealth = Humanoid.Health return end
if Info:GetAttribute("Stunned") == true then PreviousHealth = Humanoid.Health return end
AmountOfDamageDealt = PreviousHealth - Humanoid.Health
PreviousHealth = Humanoid.Health
Info:SetAttribute("Running", false)
Humanoid.WalkSpeed = 0
local HRPPosition = (HumanoidRootPart.Position + Vector3.new(math.random(-100,100) / 100,0,0))
local Direction = (HRPPosition - Info:GetAttribute("Attacked_Direction"))
if Direction.Magnitude < 0.001 then
Direction = Vector3.new(0,0,-1)
else
Direction = Direction.Unit
end
task.spawn(VectorForceModule.CreateForce,Character,HumanoidRootPart,Direction,2.5,0.1,1,Direction * 1.25)
local CurrentState = Info:GetAttribute("AnimationDebounce")
if Info:GetAttribute("AnimationDebounce") ~= true then
Info:SetAttribute("AnimationDebounce", true)
end
local Animation = KnockbackAnimations[math.random(1,#KnockbackAnimations)]
task.spawn(function()
Animation.Stopped:Wait()
Animation:AdjustSpeed(0)
task.wait(0.2)
Animation:AdjustSpeed(1)
if Info:GetAttribute("AnimationDebounce") == true and Info:GetAttribute("Stunned") ~= true then
Info:SetAttribute("AnimationDebounce", false)
Humanoid.WalkSpeed = Info:GetAttribute("OriginalWalkspeed")
end
end)
Animation:Play()
end
end)
Stunned Knockback
StunConnection = Info:GetAttributeChangedSignal("Stunned"):Connect(function()
if Info:GetAttribute("Stunned") == true and Info:GetAttribute("Blocking_Disrupted") ~= true then
Info:SetAttribute("AnimationDebounce", true)
Attack_Adjustment:SetAttribute("Godded", true)
Info:SetAttribute("Running", false)
Humanoid.WalkSpeed = 0
local HRPPosition = (HumanoidRootPart.Position + Vector3.new(math.random(-300,300) / 100,0,0))
local Direction = (HRPPosition - Info:GetAttribute("Attacked_Direction"))
if Direction.Magnitude < 0.001 then
Direction = Vector3.new(0,0,-1)
else
Direction = Direction.Unit
end
task.spawn(VectorForceModule.CreateForce,Character,HumanoidRootPart,Direction * -(5 * AmountOfDamageDealt),AmountOfDamageDealt * 10,0.1,1,Direction * Vector3.new(3,(AmountOfDamageDealt * 4.5),3))
local ActualAnimation: AnimationTrack = nil
if type(StunAnimation) == "table" then
ActualAnimation = StunAnimation[math.random(1,#StunAnimation)]
else
ActualAnimation = StunAnimation
end
task.spawn(function()
ActualAnimation:GetMarkerReachedSignal("Slowdown"):Wait()
ActualAnimation:AdjustSpeed(0.5)
end)
task.spawn(function()
ActualAnimation:GetMarkerReachedSignal("Disable"):Wait()
ActualAnimation:AdjustSpeed(1)
Humanoid.WalkSpeed = Info:GetAttribute("OriginalWalkspeed")
end)
task.spawn(function()
ActualAnimation.Stopped:Wait()
Info:SetAttribute("AnimationDebounce", false)
Info:SetAttribute("Stunned", false)
Attack_Adjustment:SetAttribute("Godded", false)
end)
ActualAnimation:Play()
end
end)
Demonstrations of the bug
Dummy being forced away
Streamable Link Watch Voxelflict - Roblox Studio 2025-01-20 12-43-21 | Streamable
Raw Link (In Case Streamable Expires) https://cdn.discordapp.com/attachments/1173144201588908042/1331001618950389934/Voxelflict_-_Roblox_Studio_2025-01-20_12-43-21.mp4?ex=6790075a&is=678eb5da&hm=480af60f8c99458d3f4d14a41dced2417115290565beca44dc9af0f460ff186a&
Players being forced away
Streamable Link Watch Server - Roblox Studio 2025-01-20 12-42-23 | Streamable
Raw Link (In Case Streamable Expires) https://cdn.discordapp.com/attachments/1173144201588908042/1331001620745551985/Server_-_Roblox_Studio_2025-01-20_12-42-23.mp4?ex=6790075b&is=678eb5db&hm=9856a61a271636cc8d52fb0e7659a9539a45f5f2cb01be8c664f9404949093bd&
Disclaimer: Multiplie Knockbacks are intentional.
Currently my issue is the following: While hitting dummies/players normally (Where the dummy/player doesn’t fall down onto the ground) repeatably works fine, stunning the dummy/player once with a force stronger than regular attacks and then hitting them with a normal attack causes the dummy/player to be forced away at a insane force (The Core Issue, players are not forced away enough with a attack that should stun players and cause large knockback. Instead, the force from the attack that should stun is being held in for a unknown reason.), which should not be possible with the variables in place to stop such force from happening. Keep in mind all the LinearVelocity
objects would have been destroyed by the time the player/dummy has no longer been stunned, so one LinearVelocity object creating this much force with parameters set in place is something I don’t understand why it’s happening.
I have also tried BodyVelocity and VectorForce. They all have had the same result. I could limit the amount of force for .MaxAxesForce
, but thats a band-aid fix to such problem.
I’ve also printed .VectorVelocity
. It does not show any NaN
values, which is weird. Thus, I’m out of ideas and in need of such help. I’ve also noticed that someone else had a similar problem that was unresolved while making this post (although their LinearVelocity properties are different, they have had the same problem with knockbacks somehow flinging players at a insane force despite having arguments in place) here. If anyone would like to help, please do!
Update: The animations, adjusting force are not the problem. It seems as if the force is being held onto the player despite already being set to a finite amount, not a insane number that causes the dummy/player to fling. I do not know what is causing that to happen. It is also exclusively only happening when the player/dummy is stunned.