NetworkOwned VRHandModels Spazzing with PrimaryPartCFrame

My goal is to stop my VR hand models (which are unanchored and networkowned by the client) from spazzing and teleporting when their cframe is modified each renderstep. The hands seem to start spazzing out and flying away sometimes coming back as if its fighting between some kind of constraint and the cframe set. Occasionally they will teleport along their upvector (this is confirmed) to and fro by a set random number each frame toggling. (what the heck is that???)

I tried changing the function to a physics step but the same thing happened again, I also compared it to a fully client sided anchored hand which worked completely perfect and points the blame at something network/physics based.

I provided videos of the hands spazzing and then acting completely normal in another instance and I have shown comments of the important parts of code (I know I threw in the entire program but I thought it would help for a full context).

Videos

Code

ALL CODE:

Server Sided VR Avatar Handler:

game.StarterGui:SetCore("VRLaserPointerMode", 0)
script.GiveAvatar.OnServerInvoke = function(player)
    -- IMPORTANT BIT LOOK AT ME AND DOWN!
	local bodygroup = Instance.new("Model")
	bodygroup.Name = player.Name
	bodygroup.Parent = game.Workspace
	local head = game.ServerStorage.Head:Clone()
	head.Parent = bodygroup
	head.Name = "Head"
	local lefthand = game.ServerStorage.LeftHand:Clone()
	lefthand.Parent = bodygroup
	lefthand.Name = "LeftHand"
	local righthand = game.ServerStorage.RightHand:Clone()
	righthand.Parent = bodygroup
	righthand.Name = "RightHand"
	bodygroup.PrimaryPart = head
	lefthand.PrimaryPart:SetNetworkOwner(player)
	righthand.PrimaryPart:SetNetworkOwner(player)
	head:SetNetworkOwner(player)
	return head,lefthand,righthand
    -- END OF IMPORTANT BIT!
end
game.Players.PlayerAdded:Connect(function(player)
	local vrenabled = game.ReplicatedFirst.VRQuery:InvokeClient(player)
	if vrenabled then
		player.CharacterAdded:Connect(function()
			print("CharacterAdded")
			player.Character:Destroy()
		end)
		player.CharacterAppearanceLoaded:Connect(function()
			print("AppearanceLoaded")
			player.Character:Destroy()
		end)
	end
end)
script.RemoveCharacter.OnServerEvent:Connect(function(player)
	player.Character:Destroy()
	player.CharacterAdded:Connect(function()
		print("CharacterAdded")
		player.Character:Destroy()
	end)
	player.CharacterAppearanceLoaded:Connect(function()
		print("AppearanceLoaded")
		player.Character:Destroy()
	end)
end)

Client Sided VR Avatar Handler: (most of this is irrelevant, I specified what is not with comments)

game.ReplicatedFirst:RemoveDefaultLoadingScreen()
local uis = game:GetService("UserInputService")
local player = game.Players.LocalPlayer
local isvrenabled = false
local isdebugenabled = false
isvrenabled = uis.VREnabled
if player.Name == "Futuristic_Paladin" then
	isvrenabled = true
	isdebugenabled = true
end
if isvrenabled then
	game.Workspace.VRAvatarScript.RemoveCharacter:FireServer()
	print("Vrenabled")
	game.StarterGui:SetCore("VRLaserPointerMode", 0)
	game.StarterGui:SetCore("VREnableControllerModels", false)
	local cam = Instance.new("Camera")
	local playergui = player:WaitForChild("PlayerGui")
	local debuggui = Instance.new("SurfaceGui")
	debuggui.Face = Enum.NormalId.Top
	debuggui.PixelsPerStud = 400
	debuggui.Parent = playergui
	debuggui.Name = "DebugGui"
	debuggui.Enabled = true
	debuggui.ClipsDescendants = true
	debuggui.AlwaysOnTop = true
	if player.Name == "Futuristic_Paladin" then
		debuggui.Enabled = true
	else
		debuggui.Enabled = false
	end
	local keycode = script:WaitForChild("KeyCode")
	local inputtype = script:WaitForChild("InputType")
	local deltagui = script:WaitForChild("Delta")
	local position = script:WaitForChild("Position")
	local offsetlabel = script:WaitForChild("Offset")
	local debuglabel = script:WaitForChild("Debug")
	keycode.Parent = debuggui
	inputtype.Parent = debuggui
	deltagui.Parent = debuggui
	position.Parent = debuggui
	offsetlabel.Parent = debuggui
	debuglabel.Parent = debuggui
	local character
	local root
	local humanoid
	local runservice = game:GetService("RunService")
    -- IMPORTANT BIT LOOK AT ME AND DOWN!
	local head,lefthand,righthand = game.Workspace.VRAvatarScript.GiveAvatar:InvokeServer()
	local reallefthand = Instance.new("Part")
	reallefthand.Parent = game.Workspace
	reallefthand.Anchored = true
	reallefthand.CanCollide = false
	reallefthand.Size = Vector3.new(0.9,0.4,0.4)
	reallefthand.Transparency = 0.5
	local realrighthand = reallefthand:Clone()
	realrighthand.Parent = game.Workspace
    -- END OF IMPORTANT BIT BUT MORE FURTHER DOWN
	local facepart = script.FacePart
	facepart.Parent = game.Workspace
	local facegui = facepart.FaceGui
	debuggui.Adornee = righthand.HandSurface
	game.Workspace.CurrentCamera:Destroy()
	cam.Parent = game.Workspace
	cam.Name = "VRCamera"
	cam.CameraType = Enum.CameraType.Scriptable
	game.Workspace.CurrentCamera = cam
	cam.CFrame = CFrame.new(Vector3.new(0,5,0))
	local lhcframe = CFrame.new(Vector3.new(1,-1,2))
	local rhcframe = CFrame.new(Vector3.new(-1,-1,2))
	local headcframe = CFrame.new(Vector3.new(10,5,0))
	local headscale = 1
	local offset = Vector3.new(0,0,0)
	local orientation = Vector3.new(90,-90,0)
	local offsetpart = Instance.new("Part")
	local camrotation = 0
	local currentrot = 0
	local turnpersec = 3
	offsetpart.Anchored = true
	offsetpart.Orientation = orientation
	offsetpart.Position = offset
	local playerheight = 5
	local function movehands(thedelta,hand)
		local handthing
		if hand == true then
			handthing = lefthand
		else
			handthing = righthand
		end
		for _,hinge in pairs(handthing:GetDescendants()) do
			if hinge:IsA("HingeConstraint") then
				local hingevalue = hinge:FindFirstChildWhichIsA("NumberValue")
				if hingevalue then
					hinge.TargetAngle = hingevalue.Value * thedelta
					hinge.ServoMaxTorque = 10000000
				end
			end
		end
	end
	local leftdelta = 0
	local rightdelta = 0
	local cameraoffset = Vector3.new(0,0,0)
	local clock = 0.02
	local movemultiplier = 10
	local debugpart = Instance.new("Part")
	debugpart.Parent = game.Workspace
	debugpart.Size = Vector3.new(1,1,1)
	debugpart.Anchored = true
	uis.InputChanged:Connect(function(input)
		--[[
		keycode.Text = tostring(input.KeyCode)
		inputtype.Text = tostring(input.UserInputType)
		position.Text = tostring(input.Position)
		--]]
		if input.KeyCode == Enum.KeyCode.Thumbstick1 then
			local success, result = pcall(function()
				cameraoffset = (cam.CFrame:ToWorldSpace(headcframe)).LookVector * movemultiplier * input.Position.Y * clock
				cameraoffset = cameraoffset + ((headcframe:ToWorldSpace(cam.CFrame)).RightVector * movemultiplier * input.Position.X * clock)
				cameraoffset = Vector3.new(cameraoffset.X,0,cameraoffset.Z)
			end)
		end
		if input.KeyCode == Enum.KeyCode.Thumbstick2 then
			if input.Position.X < 0.1 and input.Position.X > -0.1 then
				camrotation = 0
			else
				camrotation = (input.Position.X * clock * -turnpersec)
			end
		end
	end)
	debugpartplace = false
	uis.InputBegan:Connect(function(input)
		if input.KeyCode == Enum.KeyCode.ButtonX then
			debugpartplace = true
			keycode.Text = "True"
		end
		if input.KeyCode == Enum.KeyCode.ButtonA then
			uis:RecenterUserHeadCFrame()
		end
	end)
	uis.InputEnded:Connect(function(input)
		if input.KeyCode == Enum.KeyCode.ButtonX then
			debugpartplace = false
			keycode.Text = "False"
		end
	end)
	runservice.RenderStepped:Connect(function(delta)
		if currentrot > 360 then
			currentrot = currentrot -360
		end
		if currentrot < -360 then
			currentrot = currentrot + 360
		end
		clock = delta
        -- IMPORTANT BIT LOOK AT ME AND DOWN!
		cam.CFrame = cam.CFrame + cameraoffset
		currentrot = currentrot + camrotation
		cam.CFrame = CFrame.fromEulerAnglesXYZ(0,currentrot,0) + cam.CFrame.Position
		if uis.VREnabled then
			lhcframe = uis:GetUserCFrame(Enum.UserCFrame.LeftHand)
			rhcframe = uis:GetUserCFrame(Enum.UserCFrame.RightHand)
			headcframe = uis:GetUserCFrame(Enum.UserCFrame.Head)
			if headcframe then
				
			end
			if rhcframe then
				local righthandcframe = (cam.CFrame*CFrame.new(rhcframe.p*headscale))*CFrame.fromEulerAnglesXYZ(rhcframe:ToEulerAnglesXYZ())*offsetpart.CFrame
				realrighthand.CFrame = righthandcframe + righthandcframe.LookVector * 0.1
				position.Text = "R: "..tostring(righthand.PrimaryPart.CFrame)
			end
			if lhcframe then
				local lefthandcframe = (cam.CFrame*CFrame.new(lhcframe.p*headscale))*CFrame.fromEulerAnglesXYZ(lhcframe:ToEulerAnglesXYZ())*offsetpart.CFrame
				reallefthand.CFrame = lefthandcframe + lefthandcframe.LookVector * 0.1
				inputtype.Text = "L: "..tostring(lefthand.PrimaryPart.CFrame)
			end
		end
		lefthand:SetPrimaryPartCFrame(reallefthand.CFrame)
		righthand:SetPrimaryPartCFrame(realrighthand.CFrame)
		headcframe = uis:GetUserCFrame(Enum.UserCFrame.Head)
		if headcframe then
			head.CFrame = cam.CFrame:ToWorldSpace(headcframe)
		end
        -- END OF ALL IMPORTANT BITS!
		facepart.CFrame = head.CFrame + head.CFrame.LookVector * 2
		deltagui.Text = tostring(math.floor(1/clock))
		facegui.FpsLabel.Text = tostring(math.floor(1/clock))
	end)
end

Thanks for reading and responding! This is my first post I believe and although I am decently experienced in programming I make loads of mistakes, apologies if I did something stupid such as reposting or a simple 1 line bug or something.

EDIT: I figured out how to finally use the hide option yay.

1 Like