Making Knockback as Seamless as Possible

@rottendogDkR

I’ve taken your responses into consideration because it is a good point, and it solves an issue that I didn’t even realize I had. However, it still does not fix the issue from my original post. As you can see, I’ve switched to running the animations themselves client-sided and the abrupt transition is still there.

Video of issue:

New Script:

		hitbox.Touched:Connect(function(part)
			if part.Parent:FindFirstChild("Humanoid") then --if detected part is a humanoid
				hitbox:Destroy() --Prevent multiple touched events
				
				local victim = Players:GetPlayerFromCharacter(part.Parent) --easy access to hit player (If it was a player)
				
				--Attaches another sound the the victim and adds it to garbage collection queue
				wind.Parent = part.Parent.Head
				game.Debris:AddItem(wind, 5)
				
				--Take damage, play first sound
				part.Parent.Humanoid:TakeDamage(10)
				impact:Play()
				
				--Prevents characters from moving during animation
				player.Character.Humanoid.WalkSpeed = 0
				player.Character.Humanoid.JumpHeight = 0
				player.Character.Humanoid.AutoRotate = false
				
				part.Parent.Humanoid.WalkSpeed = 0
				part.Parent.Humanoid.JumpHeight = 0
				part.Parent.Humanoid.AutoRotate = false
				
				for _,v in pairs(player.Character:GetChildren()) do
					if v:IsA("BasePart") then
						v.CanTouch = false
					end
				end
				
				--adjust both characters to be facing each other and close together
				part.Parent.HumanoidRootPart.CFrame = CFrame.new(part.Parent.HumanoidRootPart.Position, player.Character.HumanoidRootPart.Position)
				player.Character.HumanoidRootPart.CFrame = part.Parent.HumanoidRootPart.CFrame * CFrame.new(0,0,-3.5) * CFrame.Angles(0,math.pi,0)
				
				animEvent:FireAllClients(player, victim, RS:FindFirstChild("ShoCharAtk", true), RS:FindFirstChild("ShoCharVic", true))
				
				local vic = part.Parent.Humanoid.Animator:LoadAnimation(RS:FindFirstChild("ShoCharVic", true))
				
				if vic.Length == 0 then
					while vic.Length == 0 do
						task.wait()
					end
				end
				
				task.delay(vic.Length, function()
					if victim then 
						hitFunc(victim, true, 1.5, 0)
						isDown[victim] = false
					end

					part.Parent.Humanoid:TakeDamage(20)
					local velocity = Instance.new("BodyVelocity", part.Parent.HumanoidRootPart)
					velocity.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
					velocity.P = 1000
					local angle = ((part.Parent.HumanoidRootPart.Position - player.Character.HumanoidRootPart.Position) * Vector3.new(10,0,10)).Unit * 70 + Vector3.new(0,5,0)
					velocity.Velocity = angle
					game:GetService("Debris"):AddItem(velocity,.3)
					part.Parent.Humanoid.WalkSpeed = 16
					part.Parent.Humanoid.JumpHeight = 7.2
					part.Parent.Humanoid.AutoRotate = true
					
					for _,v in pairs(player.Character:GetChildren()) do
						if v:IsA("BasePart") then
							v.CanTouch = true
						end
					end
					
					player.Character.Humanoid.WalkSpeed = 16
					player.Character.Humanoid.JumpHeight = 7.2
					player.Character.Humanoid.AutoRotate = true
					canPunch[player] = true
					canBlock[player] = true
					chargeEvent:FireClient(player)
					return
				end)
			end
		end)

Thank you for your help

2 Likes

Hmmm I see this is still happening in your video, for that I would try looking into Network Ownership next.

Like I said in the original post, I’m almost certain the problem is caused by the HumanoidRootPart being stationary for the duration of the animation. Changing or messing with network ownership is not going to solve the problem of the player’s body orientation switching when the animation ends.

1 Like

At least try it but if not you should make your own velocity.

What do you mean? I DID make my own velocity it’s right there in the script. I’m not sure what you’re trying to suggest?

1 Like

The only way I can think of solving this issue, assuming you are correct that it’s caused by the animation setting positional/orientational data is by not animating the movement of the target. That probably doesn’t make sense, so I’ll elaborate.

What I mean is, animate the target being launched into the air the way Roblox does player jumping animations - don’t actually make them get launched up in the animation, just make it look like they’re being launched. Then, after setting network ownership to the player throwing the other, have that player control the launching aspect so that they are actually being launched (physically, meaning the HRP is being moved with the rest of the rig), and then after they land again, launch them in whichever direction you desire. Theoretically, at least the way I imagine it playing out, this would solve the strange issue you face.

I realise you don’t want to use BodyVelocity, but it’s the only solution I can think of at the moment.

Edit: I didn’t take a look at your code, so if there’s something I’ve missed, please let me know.

I’m sorry if it was unclear, but I’m absolutely fine with using BodyVelocity as long as it turns out the way I want it to. If there is no way to get the result I want using BodyVelocity I’ll look for another way. I’ll try this method and see what I can get out of it, thanks!

2 Likes

Your own custom velocity what I mean is making your own without using instance.new and to simulate your own knock back with your own gravity.

Okay, this is something completely foreign to me, I have no idea how to do that. Could you maybe link some resources or something?

1 Like

This seems more like a BodyVelocity issue, not an animation issue. It can happen when a BodyVelocity is made on the server. Can you try changing the MaxForce from math.huge to 100000? Also I recommend setting its parent after you set it up.

local velocity = Instance.new("BodyVelocity")
velocity.MaxForce = Vector3.new(100000,100000,100000)
local angle = ((part.Parent.HumanoidRootPart.Position - player.Character.HumanoidRootPart.Position) * Vector3.new(10,0,10)).Unit * 70 + Vector3.new(0,5,0)
velocity.Velocity = angle
velocity.Parent = part.Parent.HumanoidRootPart

This was easy, I had actually already made the second change cause I remembered reading somewhere that setting the parent too early could cause jitters. Here’s the code and the results:

local velocity = Instance.new("BodyVelocity")
velocity.MaxForce = Vector3.new(100000,100000,100000)
velocity.P = 1000
local angle = ((part.Parent.HumanoidRootPart.Position - player.Character.HumanoidRootPart.Position) * Vector3.new(10,0,10)).Unit * 70 + Vector3.new(0,5,0)
velocity.Velocity = angle
velocity.Parent = part.Parent.HumanoidRootPart
game:GetService("Debris"):AddItem(velocity,.3)

Still flips over

To prevent flipping over you can disable the Humanoid’s states “Ragdoll” and “FallingDown”.

(HumanoidStateType)

I think you’re misunderstanding that part. The ragdoll is supposed to happen, it’s just the weird pause right before that is causing me trouble. Maybe it isn’t perfectly clear in this one clip, but the person being thrown flips upside down while they are in the air. At the end of the animation when they are hit, they are being hit in the back. The problem comes afterwards, when the animation ends and their body resets to the position it was in at the start of the animation, so they are facing each other again. It’s jarring and it’s like the player is T-Posing right before they get launched away

So the player that is being attacked is NOT supposed to be facing the player that is attacking him?

No. If you look in the original post you’ll see the animation performed on two grey dummies, I think the animation is much clearer there so you get the picture. Which is why in the original post I ask if maybe this specific animation is just not feasible because of the position their bodies end up in

EDIT: I should probably also mention that I really do not care how they flip or turn once they are launched, that’s perfectly fine. As long as I can fix that weird little teleport/flip right before they launch I’m a happy camper

Okay I gave it a day and I still am not sure how I should go about this. I know exactly what you’re talking about, and the concept makes sense, but I’m just thinking how I could actually launch the character in a way that still puts them in the correct position for the second attack? Like I could apply a velocity to their body like the regular jumping does, but then how could I guarantee they come back down in the right spot and at the right time to be hit and launched away at the end of the animation? I’m kind of stumped

To be honest, I’m not too sure about that either. Perhaps applying a constraint of some sort on the way down could serve as like a magnet to bring the target back to where they should be. In truth, if you design your whole system around not using predefined locations, this won’t be an issue. As long as it’s somewhere pretty close to where the target should be after they come back down, it’s just a matter of launching them from that position. This means that launching two different people from the same position might not put them exactly in the same place, but it should be close enough not to matter.

Guess I have to go look up what constraints are now lmao. I might just give up on this animation and make something different it’s just causing so many headaches. Thank you for your help though

try to tween the CFrame

look at 30 min for the knockback script

1 Like

You should probably just make a simpler knockback animation.

The problem you’re facing is as you said; the HumanoidRootPart does not move during the animation which causes the disruption between where the character was before and after the animation since the LowerTorso is in a different position.

Solutions I can think of are:

  1. Setting the HumanoidRootPart.CFrame to the same as LowerTorso.CFrame (with an offset) after the animation has ended.
  2. (Worst way) Setting the HumanoidRootPart.CFrame to where the animation would have ended, then recreating the entire animation but from that weird perspective.
  3. (Best way) Remake the animation so the start and end position of the LowerTorso is in the same place.
1 Like