My delay on my guard-break is a longer period than Normal M1 Combat

I have been making a framework for my combat for a while, and I’m nearing the end of the project so I can use it throughout my games.

  • My issue : I am nearly done with my game’s combat, but I seem to be experiencing delay, and from in comparison to my normal combat - it feels very slow on the uptake on the Guard-Break.

I questioned the flow of each process (Normal M1’s V.S Guard-Break final hit), and what tends to happen is that the way it is setup is very similar

M1 Normal Combat Client -> Client Actions/ Combat Actions ((Client-Sided) (This is usually where all the action's for each keybind is held)) -> M1 -> Server -> Combat Actions (Server) -> Hitbox -> Back to Client for Visual Effects -> DamageInterpretation (Deals with Attack Data, such as Knockback Time, whether or not Knockback will occur, etc.) -> Set State (This is shown in the picture.)

Final Hit in M1 Client -> Client Actions/ Combat Actions ((Client-Sided) (This is usually where all the action's for each keybind is held)) -> M1 -> Server -> Combat Actions (Server) -> Hitbox -> if statement to check for Count/Hit 4 + If Enemy is blocking -> Back to Client for Visual Effects -> DamageInterpretation (Deals with Attack Data, such as Knockback Time, whether or not Knockback will occur, etc.) -> Set State

I’ve tried to change the hierarchy in which the Hit/Enemy Character’s Animation and Visual Effects get placed in the Server by making it as similar as possible to my character’s normal Hit M1, with no avail.

The alternative script that is included in comparison to stop any other animations such as Blocking when they’re hit via a Listener on the Client, but otherwise I’m unsure as to why the combat is not as responsive when it comes to the Final 4th Hit the Guard-Break variant.

I think the issue lies somwhere within DamageInterpreatation, WrapperPlayer, or BridgeNet. Can you provide code snippets of those scripts?

Also, what’s the advantage of

ClientVFX:Fire(BridgeNet.AllPlayers(), Params)

over

ClientVFX:FireAllClients(Params)

?

This is BridgeNet2’s equivalence of what you showed below.
It is a networking library, I added it in hopes seeing a speed up, but unfortunately it didn’t occur.

This is ToggleState in particular’s setup

function WrapperPlayer:ToggleState(Player: Player, State: string, Truthy: boolean, Duration: number)
	if ProfilesHolders[Player.Name][State] then 
		local StateProperties = ProfilesHolders[Player.Name][State]
				
		if Truthy == true then
			StateProperties.Activity = StateProperties.OnEntry.Activity
		end
		
		if Truthy == false then
			StateProperties.Activity = StateProperties.OnExit.Activity
		end
		
		StateRemote:Fire(Player, {State = State, Activity = StateProperties.Activity})
		SignalEvents:Fire(Player, StateProperties.Name, StateProperties.Activity, Duration)
	end
	return
end

and DamageInterpretation’s full script is

function DamageInterpretation:Hurt(Character, HitChar, HitHum)
	local BodyVelo = BodyVelocity.new()
	local DMG = self.Damage
	local OGDMG = DMG

	if not HitChar then return end
	if HitChar:FindFirstChildOfClass("ForceField") then 
		return
	end
	if Character:FindFirstChildOfClass("ForceField") then 
		return 
	end
		
	local function damageHum(hum,dmg)
		local minHp = 0.3

		if hum.Health ~= minHp then
			hum.Health = math.clamp(hum.Health - dmg,minHp,math.max(hum.MaxHealth,.15))
		else
			hum.Health = minHp + 0.3
			game:GetService("RunService").Heartbeat:Wait()
			hum.Health = minHp
		end
	end

	local Player = Players:GetPlayerFromCharacter(Character)
	local ePlayer = Players:GetPlayerFromCharacter(HitChar)
	
	if PlayerWrapper:GetState(ePlayer, "Dodging") == true then 
		PlayerWrapper:ToggleState(Player, "Stunned", true, 1)
		return end

	if PlayerWrapper:GetState(ePlayer, "P-Dodging") == true then
		PlayerWrapper:ToggleState(Player, "Stunned", true, 2)
		return
	end
	
	if PlayerWrapper:GetState(ePlayer, "P-Blocking") == true then
		PlayerWrapper:ToggleState(Player, "Stunned", true, 1.5)
		return
	end
	
	
	if self.KnockBack then
		BodyVelocity.Parent = HitChar:FindFirstChild("HumanoidRootPart")
		BodyVelocity.MaxForce = Vector3.new(100000, 22500, 100000)
		BodyVelocity.Velocity = Character.HumanoidRootPart.CFrame.LookVector * 40
		task.delay(self.KnockBackTime, function()
			BodyVelocity:Destroy()
		end)
	end
	

	if self.Ragdoll then
		RagdollModule:Ragdoll(HitChar, HitChar.Variables, self.RagdollTime + 0.5)	
	end
	

	
	if self.Blockable and PlayerWrapper:GetState(ePlayer, "Blocking") == true then
		DMG = DMG/2
	end	
	
	damageHum(HitHum, DMG)
	
	if self.Blockable and self.BlockBreak then
		PlayerWrapper:ToggleState(ePlayer, "Blocking", false)
		PlayerWrapper:ToggleState(ePlayer, "Guard-Break", true)
		coroutine.wrap(function()
			task.delay(4, function()
				PlayerWrapper:ToggleState(ePlayer, "Guard-Break", false)
			end)
		end)()
		
			
		DMG = OGDMG
	end
end

Body Velocity isn’t roblox’s, instead it’s a custom made one.

I am unable to show BridgeNet2 code, because it’s actual abstractions and inner workings are foreign to me, I mainly just use the script. (I do plan to study it hopefully one day)

The video seems to be broken now, but I remember there being about a 0.5 second delay between when the animation hit the target and when the target took damage. Usually a Client → Server → Client attack takes about 0.2s, maybe 0.1 if they both have good ping. It’s always possible that your hitbox hits later than you thought you set it to.

Anyways, since I don’t know what BridgeNet.AllPlayers() actually does, I’d try switching it out for the default :FireAllClients(). It might be doing something that causes it to take a notably long time. If that still doesn’t solve the issue, you’ll just have to manually check the time it takes for certain chunks of code to run to narrow down the issue.

Something like this

function CheckTime(StartTime,Forgiveness,ctName)
	--Forgiveness is to adjust for expected delays, such as calling task.delay/wait
	ctName= Name or "Checked Time"
	print(ctName..": "..tostring(os.clock - StartTime + Forgiveness)
end
--//Example function
function BuggyFunction()
	local StartTime = os.clock()
	CheckTime(StartTime,0) --//Checked Time: ~0
	
	MysteryFunction()
	CheckTime(StartTime,0) --//If this were to return 3, that would warrant investigation (unless the function waits 3 seconds on purpose)
end

hi - just wanted to cover all bases.

double check network replication is set to 0 in studio settings.

It’s thankfully 0.

image
I’m also doing prints and checking the time in between, and I’m not seeing a single delay in use yet I see the delay is still a long time period, switched back to normal Roblox Events.


for context swinging is right before ClientVFX:FireAllClients() is fired, and Reached is the first line in the print/line in the script.