Issue with NetworkOwnership and Positions being set to nan, nan, nan

Hello, I have a serious issue with our game (Stand Proud - Roblox) related to network ownerships. It randomly started on 08/27/2023. I tried reverting to older versions of my game to check if this was due anything within our code but it still happened. All of the previous versions of the game are currently permanently bugged and it seems to be due to a Roblox error which has made our game go from 1k CCU to less than 200 CCU as it’s barely playable anymore.

Our community server and group wall is filled with people discussing this bug, where the NetworkOwnership of custom characters (stands) keep getting set to the server which causes a lot of issues. Our game has “Stands” as custom characters and the network ownership of these is set to the player they belong to. We use AlignPosition and AlignOrientation to control their movement and rotation.

So, how does this bug happen? There are three ways to replicate it:

  1. Join into the game and select a stand and it randomly happens.

  2. During PVP/or just walking around, it happens out of no where. Rare occasion but still breaks the game.

  3. Use the Barrage ability. The issue is this multiple arms effect that we have, this isn’t possible anymore as we “patched” it but we have NO clue how this was fixed, but basically, if you set the “task.delay(.25)” to literally any number higher like 0.3, it messes with the network ownership of the stand HumanoidRootPart

Some videos:
https://gyazo.com/2914f4ea406e5ed65df519edfbef0223.mp4


The barrage FX script:

local function quadBezier(p1, p2, p3, t)
	return (1 - t)^2 * p1 + 2 * (1 - t) * t * p2 + t^2 * p3
end

FX["Barrage"] = function(Character, Duration, Stretch, Length, Stand, StandName, cfr, kicks)
	local CFR = if cfr then cfr else Character.HumanoidRootPart.CFrame 
	local Stretch = Stretch or 1

	for i = 1, 2 do
		local lookTo = (CFR * CFrame.new(0,0,-10)).Position
		local P1, P2 
		local Arm 

		local function Point(Side)
			local rand1
			if Side == "Right" then
				rand1 = math.random(5,40) / 10 * Stretch
			else
				rand1 = math.random(-40, -5) / 10 * Stretch
			end

			local rand2 = math.random(-60,60) / 100 * Stretch
			local rand3 = math.random()
			local p1 = (CFR * CFrame.new(rand1,rand2,-2)).Position
			local p2 = (CFR * CFrame.new(rand1 * 2,rand2 * 6,-4)).Position

			return p1,p2
		end

		if math.random(10) > 5 then
			local CharacterArm = game.ReplicatedStorage.Stands.Arms[StandName..if kicks then "Right Leg" else "Right Arm"]:Clone()
			Arm = CharacterArm:Clone()
			Arm.Parent = workspace.Visuals
			Arm.Anchored = false	
			P1, P2 = Point("Right")
		else
			local CharacterArm = game.ReplicatedStorage.Stands.Arms[StandName..if kicks then "Left Leg" else "Left Arm"]:Clone()
			Arm = CharacterArm:Clone()
			Arm.Parent = workspace.Visuals
			Arm.Anchored = false
			P1, P2 = Point("Left")
		end



		local tA = Instance.new("Attachment")
		tA.Parent = Arm
		tA.Position = Vector3.new(-0.394,0.793,0.477)

		local bA = Instance.new("Attachment")
		bA.Parent = Arm
		bA.Position = Vector3.new(0.329, -0.847, -0.348)

		local trail = script["MotionBlur"..math.random(1,2)]:Clone()
		trail.Attachment0 = tA
		trail.Attachment1 = bA
		trail.Color = ColorSequence.new{
			ColorSequenceKeypoint.new(0, Arm.Color),
			ColorSequenceKeypoint.new(1, Arm.Color)
		}
		trail.Enabled = true
		trail.Parent = Arm
		Arm.Transparency = 1
		local count = 0
		local Connection
		local Duration = Duration or 0.7
		local Rate = 1/Duration
		task.delay(.2, function()
			for i,v in pairs(Arm:GetChildren()) do
				if v:IsA("BasePart") or v:IsA("MeshPart") then
					v.Transparency = 1
				end
				for i,f in pairs(v:GetChildren()) do
					if f:IsA("BasePart") or f:IsA("MeshPart") then
						TweenService:Create(f, TweenInfo.new(0.2), {Transparency = 1}):Play()
					end
				end
			end
			Arm.Transparency = 1
			trail.Enabled = false
			task.delay(.3, function()
				Arm:Destroy()
			end)
		end)
		Connection = RunService.Heartbeat:Connect(function(r)
			count += r * Rate
			if count > 1 then
				Connection:Disconnect()
				count = 1
			end
			if count + r * Rate <= 0.8 then
				local val = TweenService:GetValue(count, Enum.EasingStyle.Cubic, Enum.EasingDirection.Out)
				local nextVal = TweenService:GetValue(count + r * Rate, Enum.EasingStyle.Cubic, Enum.EasingDirection.Out)
				local pos = quadBezier(P1, P2, lookTo, val)
				local nextPos = quadBezier(P1, P2, lookTo, nextVal)
				Arm.CFrame = CFrame.new(pos, nextPos) * CFrame.Angles(math.rad(90),math.rad(0),math.rad(0))
			else
				local val = TweenService:GetValue(count, Enum.EasingStyle.Cubic, Enum.EasingDirection.Out)
				local pos = quadBezier(P1, P2, lookTo, val)
				Arm.CFrame = CFrame.new(pos, lookTo) * CFrame.Angles(math.rad(90),math.rad(0),math.rad(0))
			end
		end)
	end
end

One of the reasons why we are so focused on this barrage arms script is because it’s been our only form of replication of this bug, and yes, in the game right now the task.delay is set to .25 instead of .3, which does help reduce the frequency of this bug happening. It still doesn’t explain how it happens anywhere else, it is the the only clue we have and we would really appreciate to know how this happened, so that this “fix” can applied to the rest of the game’s scripts.

This causes a lot of strange issues, where the position of the HumanoidRootPart of the “stand”, in this case being the custom character is set to nan,nan,nan. The CurrentCamera’s CFrame is set to nan,nan,nan as well, disabling all shadows and making the camera stuck. I have tried setting the network ownership back to the owner through a loop manually, but the issue still persists and it seems like the network ownership is changed every frame automatically.

This issue was encountered by other people, such as:

I couldn’t find a proper cause or solution yet. Any help is greatly appreciated!

2 Likes

is this possible to change movement method instead of AlignPosition and AlignOrientation to using cframes?

2 Likes