Around 20 Frames Skipped When Starting Throw Status (RunService / PreSimulation Delay?): [PHYSICS HARD]

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’m currently working on a throw status effect (WurfP) that launches a character model in a parabolic trajectory — similar to a knockback or launch mechanic. The system works in general, but every time the status starts, about 20 frames seem to get skipped, causing a short freeze or stutter before the movement continues smoothly.

  2. What is the issue? Include screenshots / videos if possible!
    20 frames seem to get skipped**, causing a short freeze or stutter before the movement continues smoothly.

  3. What solutions have you tried so far? Did you look for solutions on the Creator Hub?
    I tried to make it deterministic, but that didn’t work either.
    After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!



function WurfP:OnStartServer()
	-- Referenzen
	local charModel = self.Character.Instance :: Model
	self.hrp       = charModel:WaitForChild("HumanoidRootPart") :: BasePart
	self.humanoid  = self.Character.Humanoid


	pcall(function() self.hrp:SetNetworkOwner(nil) end)

	self.humanoid.WalkSpeed   = 0
	self.humanoid.JumpPower   = 0
	self.humanoid.AutoRotate  = false

	-- Attacker-Referenz prüfen
	assert(self.AttackerModel and self.AttackerModel:IsA("Model"), "Wurf: AttackerModel fehlt/ist ungültig.")
	local attackerHrp = (self.AttackerModel :: Model):FindFirstChild("HumanoidRootPart") :: BasePart?
	if not attackerHrp then
		warn("Wurf: Angreifer hat kein HumanoidRootPart – Effekt endet.")
		self:End()
		return
	end

	local animator = self.humanoid:FindFirstChildOfClass("Animator") or Instance.new("Animator")
	animator.Parent = self.humanoid

	local falltrack = animator:LoadAnimation(FallAnimation)
	falltrack.Priority = Enum.AnimationPriority.Action4
	falltrack.Looped = false
--	self.Janitor:Add(falltrack, "Stop")


	falltrack:Play(0)
	falltrack:AdjustSpeed(0)

	self.t = 0
	self.GroundHit = false

	self.hrp.AssemblyLinearVelocity = Vector3.zero

	local startPos   = self.hrp.Position
	local g          = workspace.Gravity
	local speed      = self.WurfSpeed
	local angle      = math.rad(self.WurfAngle)

	-- Weg vom Angreifer
	local dir = (startPos - attackerHrp.Position)
	if dir.Magnitude < 1e-3 then dir = self.hrp.CFrame.LookVector end
	self.direction = dir.Unit

	local vxz = math.cos(angle) * speed
	local vy  = math.sin(angle) * speed
	self.duration    = (2 * vy) / g
	self.horizontalV = self.direction * vxz 

	local vec = (attackerHrp.Position - self.hrp.Position)
	vec = (attackerHrp.Position - self.hrp.Position)
	flat = Vector3.new(vec.X, 0, vec.Z)

	self.hrp.CFrame = CFrame.new(self.hrp.Position, self.hrp.Position + vec.Unit)
	-- Raycast-Parameter (für Boden + Wand)
	self._rp = RaycastParams.new()
	self._rp.FilterType = Enum.RaycastFilterType.Exclude
	self._rp.IgnoreWater = true
	self._rp.FilterDescendantsInstances = { charModel, AliveFolder, self.AttackerModel }

	local at0 = Instance.new("Attachment")
	at0.Parent = self.hrp

	local bodyVelocity = Instance.new("BodyVelocity")
	bodyVelocity.Velocity = self.hrp.CFrame.LookVector * 100 -- Geschwindigkeit des Projektils
	bodyVelocity.MaxForce = Vector3.new(10000, 10000, 10000) -- Maximale Kraft
	bodyVelocity.Parent = at0

	local once = true
	local Wandrichtung = -self.hrp.CFrame.LookVector * 2
	local Bodenrichtung = Vector3.new(0,-5,0) 
	
	local startAt = self.t + self.delayBeforeStart
	
	self.connection = RunService.PreSimulation:Connect(function(dt)
		self.t += dt
		if self.t <= self.delayBeforeStart then return end
		local t = self.t - self.delayBeforeStart
		local vyNow = vy - g * t
		
		self.hrp.AssemblyLinearVelocity = self.horizontalV + Vector3.new(0, vyNow, 0)
		if once == true then
			once = false
			falltrack:AdjustSpeed(falltrack.Length/self.duration)
			self.animcon = falltrack:GetMarkerReachedSignal("EndFlying"):Connect(function()
				falltrack:AdjustSpeed(0)
				self.Janitor:Add(self.animcon, "Disconnect")
			end)
		end
		
		local Boden = workspace:Raycast(self.hrp.Position, Bodenrichtung, self._rp)
		

		if (self.duration + self.delayBeforeStart) <= self.t then
			print("Ende")
			task.wait(0.3)
			self:End()
			local victimWCS = WCS.Character.GetCharacterFromInstance(self.AttackerModel)
			--local knockback = Knockback.new(victimWCS, 
			--self.Character.Instance, 10, 1.4, -self.hrp.CFrame.LookVector, "Default")
			--knockback:Start()
		end
	end) 
	
	--self.hrp:SetNetworkOwner(nil)
	
	task.delay(0.3, function()
		task.spawn(function()
			self.hrp.Touched:Connect(function(hit)
				if hit:IsDescendantOf(charModel) then return end
				print(hit.Name)
				--falltrack:Stop(0.2)
				local victimWCS = WCS.Character.GetCharacterFromInstance(self.AttackerModel)
				local knockback = Knockback.new(victimWCS, self.Character.Instance, 10, 1.4, -self.hrp.CFrame.LookVector, "Default")
				knockback:Start()
			end)
		end)
	end)
	
	local function isGround(part: BasePart): boolean
		if part:IsDescendantOf(charModel) then return false end
		if AliveFolder and part:IsDescendantOf(AliveFolder) then return false end
		return true
	end

	--local victimWCS = WCS.Character.GetCharacterFromInstance(self.AttackerModel)
	--local knockback = Knockback.new(victimWCS, self.Character.Instance, 10, 1.4, -self.hrp.CFrame.LookVector)
	--	knockback:Start()

	-- Janitor
	self.Janitor:Add(self.connection, "Disconnect")
end

function WurfP:OnEndServer()
	self.Janitor:Cleanup()
	if self.hrp and self.hrp:IsDescendantOf(workspace) then
		self.hrp.AssemblyLinearVelocity = Vector3.zero
	end
end

return WurfP 
-- This is an example Lua code block

Here a video so you can understand better:

maybe try setting the network owner to nil after its launched?

No this definitely does not solve it unfortunately

This is 100% a Roblox Studio Bug since in other Development Studios like Unreal Engine it does work actually.

1 Like