Body Velocity Knockback going in the wrong direction for players

You can write your topic however you want, but you need to answer these questions:

  1. **What do you want to achieve? ** Keep it simple and clear!
    I want to create a Super Blox Bros knockback system.
  2. **What is the issue? ** Include screenshots / videos if possible!
    The knockback system was working fine, until one day the knockback was suddenly acting wonky for players. When attacking other players, the knockback is slightly offsite upwards, but on regular dummies, it worked just fine.
  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I’ve been looking for solutions all evening, haven’t found any that’s helped so far.
    If anyone has any idea about why this is happening, please tell me. I will provide videos if neccessary.
local bVelocity = {}

local replicated = game:GetService("ReplicatedStorage")
local eModule = require(replicated.Modules.Effects)
local KeyModule = require(replicated.Modules.GetKeyDownServer)
local waitforinput = replicated.RemoteFunctions.WaitForKeyInput
local stunModule = require(replicated.Modules.StunModule)
local RS = game:GetService("ReplicatedStorage")
local debris = game:GetService("Debris")

local function PSoundNormal(id, lifetime, volume)

	local sound = Instance.new("Sound", workspace.Fx)
	sound.SoundId = id
	sound.Volume = volume
	sound:Play()
	game:GetService("Debris"):AddItem(sound, lifetime)
end

local function hWait(amount)
	
	local i = 0
	
	repeat
		game:GetService("RunService").Heartbeat:Wait()
		i += 1
	until i >= amount
end

local function PSound(id, radius, lifetime, character, volume)

	local sound = Instance.new("Sound", workspace.Fx)
	sound.Parent = character.PrimaryPart
	sound.RollOffMode = Enum.RollOffMode.Linear
	sound.RollOffMaxDistance = radius
	sound.RollOffMinDistance = 0
	sound.SoundId = id
	sound.Volume = volume
	sound:Play()
	game:GetService("Debris"):AddItem(sound, lifetime)


end

Code:
function bVelocity.InflictVelocity(Player:Player, Target:Model, KGB:number, BKB:number, Angle:number, Damage:number, BM:number)
	
	--Angle is set from -360 to 360.
	
	local Thumanoid:Humanoid = Target.Humanoid
	local aprilFools = false
	local visualize = false
	local wasInAir = false
	
	if Thumanoid.FloorMaterial == Enum.Material.Air then
		wasInAir = true
	end
	
	
	-- Values.
	local characterName = Target:FindFirstChild("CharacterName")
	local Percent = Target.percentValue

	
	local characterWeightValues = {
		URC = 100;
		Noob = 80;
		Bloogis = 85;
		BeachGunner = 72;
		Virus = 87
	}
	
	local Weight = 85 --would be weight of the target
	
	if characterName ~= nil then
		Weight = characterWeightValues[characterName.Value]
	end
	
	
	
	local Scaling = KGB/100
	local Ratio = 2.0
	
	-- Nerdy knockback calculation.
	local KnockbackCalculation = (((((Percent.Value/10 + Percent.Value*Damage/16) * 200/Weight+100 + 1.4) + 18) * Scaling) + BKB) * Ratio
	
	if aprilFools == true then
		KnockbackCalculation = 15000
	end
	
	if Target.percentValue.Value > 100 then
		KGB *= 1 + ((Percent.Value - 100) / 100)
	end
	
	local LaunchSpeed = KnockbackCalculation*0.03 
	BM = BM or 1
	LaunchSpeed *= BM
	
	local Knockback = Instance.new("BodyVelocity")
	
	local LForce = LaunchSpeed * 3
	local LBack = 60
	local HBack = 88
	local diff = HBack - LBack
	-- yields 28
	local range = LForce - LBack
	
	for i, v in pairs(Target.PrimaryPart:GetChildren()) do
		if v:IsA("BodyVelocity") then
			v:Destroy()
		end
	end
	
	if Angle == 361 then
		
		if Thumanoid.FloorMaterial == Enum.Material.Air then
			Angle = 38
		else
			if LForce <= LBack then
				Angle = 0
			elseif LForce > LBack and LForce < HBack then
				--[[
					Creates a linear range between values, yielding a value between 0 and 1 
					for percent Change.
				]]
				Angle = 38 * (range/28)
			elseif LForce >= HBack then
				Angle = 38
			end
		end
	end
	
	print(Angle, "Angle 361 change")
	
	-- Create a new part to calculate angles.
	
	local newAnglePart = Instance.new("Part")
	newAnglePart.Parent = workspace
	newAnglePart.CanCollide = false
	newAnglePart.Transparency = 1
	newAnglePart.CanQuery = false
	newAnglePart.CanTouch = false
	newAnglePart.Anchored = true
	
	-- Make a part at the Primary Part to launch a player at an angle
	local hrpFrame = Player.Character.PrimaryPart.CFrame
	newAnglePart.CFrame = hrpFrame
	newAnglePart.CFrame = newAnglePart.CFrame * CFrame.Angles(math.rad(Angle), 0, 0)
	
	local angleRay = Ray.new(newAnglePart.CFrame.Position, newAnglePart.CFrame.LookVector * LaunchSpeed * 3.8)
	
	local function RayToPart(ray)
		--this function takes the ray as a parameter. Below, it gets the midpoint.
		local MidPoint = ray.Origin + ray.Direction/2

		--below it creates the part and returns it. I'm sure you're familiar with properties
		local Part = Instance.new("Part")
		Part.Anchored = true
		Part.CFrame = CFrame.lookAt(MidPoint, ray.Origin)
		Part.Size = Vector3.new(1, 1, ray.Direction.Magnitude/1.5)
		Part.Parent = workspace
		Part.CanCollide = false
		Part.Transparency = 1
		
		debris:AddItem(Part, 2)
		
		return Part
	end
	
	local function IsGround()
		
		if Angle > 0 and Angle < 361 then
			return false
		end
		
		local blackList = RaycastParams.new()
		blackList.FilterType = Enum.RaycastFilterType.Blacklist
		blackList.FilterDescendantsInstances = {Target}
		
		local direction = Vector3.new(0, -3, 0)
		
		local origin = Target.PrimaryPart.Position
		
		local newRay = workspace:Raycast(origin, direction, blackList)
		
		if newRay then
			if newRay.Instance then
				return true
			else
				return false
			end
		else
			return false
		end
		
	end
	
	RayToPart(angleRay)
	

	
	
	
	--local designatedPointReference = newAnglePart.CFrame * CFrame.new(0,0, LaunchSpeed)
	
	
	
	
	
	if LaunchSpeed >= 40 then
		require(RS.Modules.StunModule).AddStun(Target, 1)
		require(RS.Modules.StunModule).AddStun(Player.Character, 1)
		
		PSound("rbxassetid://8821028196", 100, 1.3, Target, 8)
		eModule.BasicEffect("SMASH!!!", 8, Target)
		
		local newZoom = Instance.new("StringValue")
		
		Player.Character.PrimaryPart.Anchored = true
		Target.PrimaryPart.Anchored = true
		
		newZoom.Name = "ZoomIn"
		newZoom.Parent = Player.Character
		debris:AddItem(newZoom, 1)
		
		local pAnimator:Animator = Player.Character.Humanoid.Animator
		
		
		for i, track:AnimationTrack in pairs(pAnimator:GetPlayingAnimationTracks()) do
			
			track:AdjustSpeed(0)
			task.delay(1, function()
				track:AdjustSpeed(1)
			end)
		end
		
		local newZoomTwo = Instance.new("StringValue")
		
		newZoomTwo.Name = "ZoomIn"
		newZoomTwo.Parent = Target
		debris:AddItem(newZoomTwo, 1)
		
		local tAnimator:Animator = Target.Humanoid.Animator
		
		for i, track:AnimationTrack in pairs(tAnimator:GetPlayingAnimationTracks()) do
			track:AdjustSpeed(0)
			task.delay(1, function()
				track:AdjustSpeed(1)
			end)
		end
		
		task.wait(1)
		
		Player.Character.PrimaryPart.Anchored = false
		Target.PrimaryPart.Anchored = false
	end
	
	Target.PrimaryPart.Anchored = false
	
	local finalizedAngle = Angle
	
	
	--[[
	if Target.PrimaryPart:FindFirstChild("Velocity") then
		local prevAngle = Target.PrimaryPart:FindFirstChild("Velocity"):GetAttribute("Angle")
		
		local distanceBetweenAngles = math.abs(Angle - prevAngle)
		
		if Angle < prevAngle then
			finalizedAngle = Angle + (distanceBetweenAngles / 2)
		elseif Angle > prevAngle then
			finalizedAngle = prevAngle + (distanceBetweenAngles / 2)
		end
		
		Target.PrimaryPart:FindFirstChild("Velocity"):Destroy()
		
	end
	
	]]
	
	
	Angle = finalizedAngle
	
	print(Angle, "Angle finalized change")
	
	Knockback.Parent = Target.HumanoidRootPart
	Knockback.Name = "Velocity"
	Knockback.MaxForce = Vector3.new(20000, 20000, 0)
	Knockback:SetAttribute("Angle", Angle)
	
	
	local identifier = Instance.new("StringValue")
	identifier.Name = "DontKick"
	identifier.Parent = Knockback
	
	
	local pressedAnything = false
	
	local pressedConnection = nil
	pressedConnection = Thumanoid:GetPropertyChangedSignal("MoveDirection"):Connect(function()
		pressedAnything = true
		pressedConnection:Disconnect()
	end)
	
	
	
	local launchModifier = math.clamp((LaunchSpeed * 3.8/100), .05, 0.6)
	local launchTimeTicker = tick()
	
	
	local launchTime = (.2 +launchModifier)
	local AfterTime = (launchTime - .2)
	local hAfterTime = AfterTime / 2
	
	if game:GetService("Players"):GetPlayerFromCharacter(Target) then
		local newTag = Instance.new("ObjectValue")
		newTag.Value = Player
		newTag.Parent = Target
		newTag.Name = "DeathTag"
		debris:AddItem(newTag, launchTime * 2)
	end
	
	
	debris:AddItem(Knockback,launchTime)
	
	local stun = require(RS.Modules.StunModule)
	local launchStun = stun.AddStun(Target, launchTime)
	-- Send them flying at this Angle
	
	local CappedVelocity = newAnglePart.CFrame.LookVector * LaunchSpeed * 3.8
	print(newAnglePart.CFrame.LookVector)
	
	local function backOrFront(root1, root2)
		local ObjectSpace = root2.CFrame:inverse() * root1.CFrame
		if ObjectSpace.Z > 0 then
			return "HitFromBack"
		else
			return "HitFromFront"
		end
	end
	
	-- gets if hit from front or back, then turns it into a string
	local hitFrom = backOrFront(Player.Character.PrimaryPart, Target.PrimaryPart)
	
	-- Uses that string to decide what animation to pick.
	local hitAnimation = script.KB:FindFirstChild(hitFrom)
	
	local load:AnimationTrack = Thumanoid.Animator:LoadAnimation(hitAnimation)
	load.Name = hitFrom
	
	if Angle >= 0 and Angle <= 85 then
		load:Play()
	elseif Angle > 85 and Angle <= 105 then
		load = Thumanoid.Animator:LoadAnimation(script.KB.HitFromUp)
		load:Play()
	end
	
	Knockback.Destroying:Connect(function()
		load:Stop()
	end)
	
	

	
	Knockback.Velocity = CappedVelocity
	
	
	local landedConnection = nil
	--[[landedConnection = Thumanoid.StateChanged:Connect(function(old, new)
		if new == Enum.HumanoidStateType.Landed and Angle > 0 and Angle < 360 then

			if Knockback and pressedAnything == false then else return end

			Angle = -Angle
			print(Angle, "Angle reversed change")
			Knockback:Destroy()
			landedConnection:Disconnect()

			local RS = game:GetService("ReplicatedStorage")
			local tweenService = game:GetService("TweenService")

			local function slamEffect(position:Vector3):MeshPart
				local newSlam = RS.Effects.HitWave:Clone()

				newSlam.Position = position
				newSlam.Parent = workspace

				local goals = {
					Transparency = 1;
					Size = Vector3.new(20, 2, 20)
				}

				local inf = TweenInfo.new(.4, Enum.EasingStyle.Quad, Enum.EasingDirection.In)

				local newTween = tweenService:Create(newSlam, inf, goals)
				newTween:Play()

				debris:AddItem(newSlam, 1)
				return newSlam

			end

			slamEffect(Target.PrimaryPart.Position - Vector3.new(0, 2.25, 0))
			PSoundNormal("rbxassetid://5246111377", 2, 2)

			local groundHitAnimation:AnimationTrack = Thumanoid.Animator:LoadAnimation(script.GroundHit)
			groundHitAnimation:Play()

			groundHitAnimation:GetMarkerReachedSignal("GroundEnd"):Connect(function()

				local bigStun = stunModule.AddStun(Target, "INF", true, 270)
				local groundStayingAnimation:AnimationTrack = Thumanoid.Animator:LoadAnimation(script.GroundLong)
				groundStayingAnimation:Play()

				local input:Enum.KeyCode = nil
				local inputScript
				if game:GetService("Players"):GetPlayerFromCharacter(Target) ~= nil then

					local tPlayer = game:GetService("Players"):GetPlayerFromCharacter(Target)
					inputScript = task.spawn(function()
						input = waitforinput:InvokeClient(tPlayer)
					end)
				end

				local longevity = 0
				local stunned = false

				repeat
					task.wait(.01)
					longevity += 0.1
					for i, v in pairs(Target:GetChildren()) do
						if v.Name == "Stun" and v:IsA("IntValue") then
							if v == launchStun or v.Value == 270 then else 
								stunned = true
							end
						end
					end
				until stunned == true or longevity >= 10 or input ~= nil
				
				
				
				groundStayingAnimation:Stop()
				bigStun:Destroy()
				
				coroutine.yield(inputScript)
				local iframes = require(RS.Modules.IFrameModule)
				local velocity = require(RS.Modules.BodyVelocity)
				local playerHumanoid = Player.Character:FindFirstChild("Humanoid")
				local rightOri = Vector3.new(0, -90, 0)
				local leftOri = Vector3.new(0, 90, 0)
				
				if input ~= nil then
					if input == Enum.KeyCode.A then

						local hrp = Target.HumanoidRootPart

						local anim = nil

						if hrp.Orientation == rightOri then

							velocity.InflictVelocity(Target, Target.PrimaryPart.CFrame.LookVector * -40, nil, .2)
							anim = Thumanoid.Animator:LoadAnimation(script.BFlip)

						elseif hrp.Orientation == leftOri then

							velocity.InflictVelocity(Target, Target.PrimaryPart.CFrame.LookVector * 40, nil, .2)
							anim = Thumanoid.Animator:LoadAnimation(script.FFlip)

						end

						if anim ~= nil then
							anim:Play()
						end

						iframes.AddIFrames(Target, .65)
						stun.AddStun(Target, 1.15, true, "sak")
					elseif input == Enum.KeyCode.D then
						local hrp = Target.HumanoidRootPart

						local anim = nil

						if hrp.Orientation == rightOri then

							velocity.InflictVelocity(Target, Target.PrimaryPart.CFrame.LookVector * 40, nil, .2)
							anim = Thumanoid.Animator:LoadAnimation(script.FFlip)

						elseif hrp.Orientation == leftOri then

							velocity.InflictVelocity(Target, Target.PrimaryPart.CFrame.LookVector * -40, nil, .2)
							anim = Thumanoid.Animator:LoadAnimation(script.BFlip)

						end

						if anim ~= nil then
							anim:Play()
						end

						iframes.AddIFrames(Target, .65)
						stun.AddStun(Target, 1.15, true, "sak")
					end
				elseif stunned == false then
					iframes.AddIFrames(Target, 1, true)
				end

			end)

		end
	end)]]
	
	-- Slows down momentum
	local pastAngle = Angle
	local timesBounce = 0
	
	local function bounce()
		
		local flippedAngle = -Angle
		
		print(flippedAngle, "Flipped angle")
		timesBounce += 1
		
		newAnglePart.CFrame = hrpFrame
		newAnglePart.CFrame = newAnglePart.CFrame * CFrame.Angles(math.rad(flippedAngle), 0, 0)
		
		local lifetimeLeft = launchTime - (tick() - launchTimeTicker)
		
		Knockback.Velocity = (newAnglePart.CFrame.LookVector * LaunchSpeed * (3.8 / timesBounce))
		
		task.spawn(function()
			local wat = "?"
			repeat 
				task.wait(.05) lifetimeLeft = launchTime - (tick() - launchTimeTicker)
				if IsGround() == true then
					bounce()
					wat = true
					return
				end
			until lifetimeLeft <= 0 or wat == true
			
			
		end)
		
		
		
	end
	
	task.delay(.2, function()
		
		if Angle < 0 or Angle < 5 then
			Knockback:Destroy()
		else
			
			
			for i = 10, 1, -1 do
				
				local momentumLoss = (newAnglePart.CFrame.LookVector * LaunchSpeed * 3.8) * (i / 10)

				
				
				if Angle > 0 and Angle ~= 361 then
					newAnglePart.CFrame = hrpFrame
					newAnglePart.CFrame = newAnglePart.CFrame * CFrame.Angles(math.rad(pastAngle * (i / 10)), 0, 0)
				end
				
				Knockback.Velocity = momentumLoss
				task.wait(hAfterTime / 10)
				
				if visualize == true then
					local newPart = workspace.SpecialValues.LaunchShower:Clone()
					newPart.Parent = workspace
					newPart.CFrame = Target.PrimaryPart.CFrame
					debris:AddItem(newPart,2)
				end
				
			end
			
			for i = 1, 10 do
				local lessVel = (newAnglePart.CFrame.LookVector * LaunchSpeed * 3.8) * (i / 10) * 1.2
				
				if Angle > 0 and Angle ~= 361 then
					newAnglePart.CFrame = hrpFrame
					newAnglePart.CFrame = newAnglePart.CFrame * CFrame.Angles(math.rad(-pastAngle * (i / 10)), 0, 0)
				end
				
				Knockback.Velocity = lessVel * (1 - (i / 10))
				task.wait(hAfterTime / 10)
				
				if visualize == true then
					local newPart = workspace.SpecialValues.LaunchShower:Clone()
					newPart.Parent = workspace
					newPart.CFrame = Target.PrimaryPart.CFrame
					debris:AddItem(newPart, 2)
				end
				
				
				if i == 5 then
					debris:AddItem(launchStun, 0)
					if visualize == true then
						local newPart = workspace.SpecialValues.LaunchShower:Clone()
						newPart.Parent = workspace
						newPart.CFrame = Target.PrimaryPart.CFrame
						newPart.BrickColor = BrickColor.new("Lime green")
						debris:AddItem(newPart, 2)
					end
				end
			
				
				
			end
			Knockback:Destroy()
			
			
			
		end
		
		
		
		
	end)
	
	--Create a trail of smoke
	task.spawn(function()
		
		if LaunchSpeed >= 8 and Angle >= 15 and Angle < 361 then
			
			local timeOfSmoke = .2 + hAfterTime
			
			local sEffect = game:GetService("ReplicatedStorage").Effects.Smoke:Clone()
			
			sEffect.Parent = Target.Torso
			
			task.delay(timeOfSmoke, function()
				sEffect.Enabled = false
				task.wait(2)
				sEffect:Destroy()
			end)

			
		end
		
	end)
	
	
	
	
	
	if LaunchSpeed >= 19 and Thumanoid.FloorMaterial == Enum.Material.Air then
		
		if Angle > 15 and Angle < 360 then
			--Tumble script for stun
			local load = Target.Humanoid.Animator:LoadAnimation(script:FindFirstChild("Tumble"))
			

			load:Play()


			task.delay(math.clamp(KnockbackCalculation/60, 0, 1), function()
				load:Stop()
			end)

			local con 

			con = Thumanoid:GetPropertyChangedSignal("FloorMaterial"):Connect(function()
				if Thumanoid.FloorMaterial ~= Enum.Material.Air then
					load:Stop()
					con:Disconnect()
					if game:GetService("Players"):GetPlayerFromCharacter(Target) then
						script.GroundedRemoteEvent:FireClient(game:GetService("Players"):GetPlayerFromCharacter(Target))
					end
				end
			end)
		end
		
	end
	
	
	
	
	-- Delete the angle part
	debris:AddItem(newAnglePart,4)
	
end
	
	
	
	--[[local amount = 0
	for _, child in pairs(target:GetChildren()) do
		if child.ClassName == "BodyVelocity" and child.Name == "Velocity" then
			amount += 1
		end
	end

	if amount > 1 then
		for _, child in pairs(target:GetChildren()) do
			if child.ClassName == "BodyVelocity" and child.Name == "Velocity" then
				debris:AddItem(child, 0)
			end
		end
	end
	
	local bv = Instance.new("BodyVelocity")
	
	bv.Velocity = velocity
	bv.MaxForce = Vector3.new(20000, 20000, 0)
	bv.Parent = target.HumanoidRootPart
	bv.Name = "Velocity"
	debris:AddItem(bv, lifetime)
	

	local biggestValue = 0
	
	if math.abs(velocity.X) > math.abs(velocity.Y) then
		biggestValue = math.abs(velocity.X)
	elseif math.abs(velocity.X) < math.abs(velocity.Y) then
		biggestValue = math.abs(velocity.Y)
	else
		biggestValue = math.abs(velocity.Y)
	end
	
	
	
	if noEffects == nil or noEffects == false or DOEFFECTS == true then
		if biggestValue >= 50 and target.Torso:FindFirstChild("BodyFrontAttachment") then

			local newSmoke = game:GetService("ReplicatedStorage").Effects.Smoke:Clone()
			newSmoke.Parent = target.Torso.BodyFrontAttachment
			local GraphicsLevel = UserSettings().GameSettings.SavedQualityLevel.Value
			local oldRate = newSmoke.Rate
			newSmoke.Rate = oldRate * 10 / GraphicsLevel

			task.delay(lifetime * 2 + .8, function()
				newSmoke.Enabled = false
				wait(2)
				debris:AddItem(newSmoke, 0)
			end)
		elseif DOEFFECTS == true then
			local newSmoke = game:GetService("ReplicatedStorage").Effects.Smoke:Clone()
			newSmoke.Parent = target.Torso.BodyFrontAttachment
			local GraphicsLevel = UserSettings().GameSettings.SavedQualityLevel.Value
			local oldRate = newSmoke.Rate
			newSmoke.Rate = oldRate * 10 / GraphicsLevel

			task.delay(lifetime * 2 + .8, function()
				newSmoke.Enabled = false
				wait(2)
				debris:AddItem(newSmoke, 0)
			end)
		end

		if biggestValue > 100 then
			PSoundNormal("rbxassetid://9057675920", 4, 5)
			eModule.BasicEffect("SmashEffect", .4, target)
			
		end
	end--]]
	

return bVelocity

This video shows the intended angle (part) and the actual angle, where the noob is sent.

1 Like

Can you highlight the line where you apply the velocity and what formula you use for it? The code is very long.

No problem, give me an hour since I just woke up

nevermind :sweat_smile: looks like it was an issue from one of my other scripts. Sorry if I wasted your time

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.