How can I make my vr model move through the air

Games like “sked’s vr playground” let you press ButtonR1 to propel yourself in the direction your right hand is facing, how can I do a similar thing?

I followed the dev forum to make a vr system with hands but I am not sure how to make myself move.

Here is my script (in ServerScriptService):

game.ReplicatedStorage.VREvent.OnServerEvent:Connect(function(player, mode, query)
	if mode == "Start" then
		local char = player.Character
		
		local vrModel = game.ReplicatedStorage.PlrParts:Clone()
		vrModel.Parent = workspace
		vrModel.Name = player.Name.."VRModel"
		
		vrModel:PivotTo(char.PrimaryPart.CFrame)
		
		local head:Part = vrModel.Head
		local lefthand:Part = vrModel.LeftHand
		local righthand:Part = vrModel.RightHand

		local bodyColors = char:FindFirstChildOfClass("BodyColors")
		
		head.Color = bodyColors.HeadColor3
		lefthand.Color = bodyColors.LeftArmColor3
		righthand.Color = bodyColors.RightArmColor3
		
		--[[for _, v in pairs(char:GetChildren()) do
			if v:IsA("Accessory") then
				local clone = v:Clone()
				clone.Parent = vrModel
				
				local handle = clone.Handle
				
				for _, x in pairs(head:GetChildren()) do
					if x:IsA("Attachment") and handle:FindFirstChild(x.Name) then
						local accessoryWeld = handle:FindFirstChild("AccessoryWeld")
						accessoryWeld.Part0 = head
						accessoryWeld.Part1 = handle
						
						handle.CFrame = head:FindFirstChild(x.Name).CFrame
					end
				end
			end
		end]]--
		
		game.ReplicatedStorage.VREvent:FireClient(player, vrModel)
	elseif mode == "Update" then
		local vrModel:Model = query.vrModel
		local head:Part = vrModel.Head
		local lefthand:Part = vrModel.LeftHand
		local rightHand:Part = vrModel.RightHand
		
		local headcframe = query.headcframe
		local lefthandcframe = query.lefthandcframe
		local righthandcframe = query.righthandcframe
		
		head.CFrame = headcframe
		lefthand.CFrame = lefthandcframe
		rightHand.CFrame = righthandcframe
	end
end)

(I was unable to figure out how to attach accessories to the VRModel)

Then here is my localscript (in StarterCharacter):

local rs = game:GetService("RunService")
local vr = game:GetService("VRService")

local cc = workspace.CurrentCamera
local player = game.Players.LocalPlayer
local char = player.Character

local headscale = 1
local vrevent = game.ReplicatedStorage:WaitForChild("VREvent")

if vr.VREnabled == true then
	print(player.Name.." has VR enabled :)")
	vrevent:FireServer("Start")
else
	print(player.Name.." does not have VR enabled :(")
end

vrevent.OnClientEvent:Connect(function(vrModel)
	cc.HeadScale = headscale
	cc.CameraType = Enum.CameraType.Scriptable
	
	local clientModel = workspace:FindFirstChild(player.Name.."VRModel"):Clone()
	clientModel.Parent = workspace
	clientModel.Name = player.Name.."ClientVRModel"
	
	local highlight = Instance.new("Highlight")
	highlight.Parent = clientModel
	highlight.FillTransparency = 1
	highlight.OutlineTransparency = 0.7
	
	local head:Part = clientModel.Head
	local lefthand:Part = clientModel.LeftHand
	local rightHand:Part = clientModel.RightHand
	
	for i, v in pairs(clientModel:GetDescendants()) do
		if v:IsA("BasePart") and v ~= lefthand and v ~= rightHand then
			v.Transparency = 1
		elseif v:IsA("Decal") or v:IsA("Texture") then
			v.Transparency = 1
		end
	end
	
	vrModel:Destroy()

	vr:RecenterUserHeadCFrame()
	
	rs.RenderStepped:Connect(function()
		local headcframe = vr:GetUserCFrame(Enum.UserCFrame.Head)
		local lefthandcframe = vr:GetUserCFrame(Enum.UserCFrame.LeftHand)
		local righthandcframe = vr:GetUserCFrame(Enum.UserCFrame.RightHand)

		head.CFrame = (cc.CFrame*CFrame.new(headcframe.Position*headscale))*CFrame.fromEulerAnglesXYZ(headcframe:ToEulerAnglesXYZ())
		lefthand.CFrame = (cc.CFrame*CFrame.new(lefthandcframe.Position*headscale))*CFrame.fromEulerAnglesXYZ(lefthandcframe:ToEulerAnglesXYZ())
		rightHand.CFrame = (cc.CFrame*CFrame.new(righthandcframe.Position*headscale))*CFrame.fromEulerAnglesXYZ(righthandcframe:ToEulerAnglesXYZ())

		cc.CFrame = headcframe
		
		vrevent:FireServer("Update", {
			vrModel = vrModel,
			headcframe = head.CFrame,
			lefthandcframe = lefthand.CFrame,
			righthandcframe = rightHand.CFrame
		})
	end)
end)
1 Like

I can also provide my VRModel if it helps

1 Like

You can just get the CFrame of your hand and (I recommend at least) use AlignPosition to change the position of the vr model. AlignPosition would automatically replicate to server as well.

Will this work if the parts are anchored? Like head and arms?

No, you need to unanchor the parts.

I’ve never used an align position before but I tried to make it work but I still don’t know how to use it.

local uis = game:GetService("UserInputService")
local rs = game:GetService("RunService")
local vr = game:GetService("VRService")

local cc = workspace.CurrentCamera
local player = game.Players.LocalPlayer
local char = player.Character

local headscale = 1
local vrevent = game.ReplicatedStorage:WaitForChild("VREvent")

if vr.VREnabled == true then
	print(player.Name.." has VR enabled :)")
	vrevent:FireServer("Start")
else
	print(player.Name.." does not have VR enabled :(")
end

vrevent.OnClientEvent:Connect(function(vrModel)
	cc.HeadScale = headscale
	cc.CameraType = Enum.CameraType.Scriptable

	local clientModel = workspace:FindFirstChild(player.Name.."VRModel"):Clone()
	clientModel.Parent = workspace
	clientModel.Name = player.Name.."ClientVRModel"

	local highlight = Instance.new("Highlight")
	highlight.Parent = clientModel
	highlight.FillTransparency = 1
	highlight.OutlineTransparency = 0.7

	local head:Part = clientModel.Head
	local lefthand:Part = clientModel.LeftHand
	local rightHand:Part = clientModel.RightHand

	local front = head.Front

	local alignposition = Instance.new("AlignPosition")
	alignposition.Parent = head
	alignposition.Mode = Enum.PositionAlignmentMode.OneAttachment
	alignposition.Attachment0 = head.Main
	alignposition.Responsiveness = 200
	alignposition.Enabled = false

	for i, v in pairs(clientModel:GetDescendants()) do
		if v:IsA("BasePart") and v ~= lefthand and v ~= rightHand then
			v.Transparency = 1
		elseif v:IsA("Decal") or v:IsA("Texture") then
			v.Transparency = 1
		end
	end

	vrModel:Destroy()

	vr:RecenterUserHeadCFrame()

	rs.RenderStepped:Connect(function()
		alignposition.Position = front.Position
		
		local headcframe = vr:GetUserCFrame(Enum.UserCFrame.Head)
		local lefthandcframe = vr:GetUserCFrame(Enum.UserCFrame.LeftHand)
		local righthandcframe = vr:GetUserCFrame(Enum.UserCFrame.RightHand)

		head.CFrame = (cc.CFrame*CFrame.new(headcframe.Position*headscale))*CFrame.fromEulerAnglesXYZ(headcframe:ToEulerAnglesXYZ())
		lefthand.CFrame = (cc.CFrame*CFrame.new(lefthandcframe.Position*headscale))*CFrame.fromEulerAnglesXYZ(lefthandcframe:ToEulerAnglesXYZ())
		rightHand.CFrame = (cc.CFrame*CFrame.new(righthandcframe.Position*headscale))*CFrame.fromEulerAnglesXYZ(righthandcframe:ToEulerAnglesXYZ())

		cc.CFrame = headcframe

		vrevent:FireServer("Update", {
			vrModel = vrModel,
			headcframe = head.CFrame,
			lefthandcframe = lefthand.CFrame,
			righthandcframe = rightHand.CFrame
		})
	end)

	uis.InputBegan:Connect(function(input, processed)
		if input.KeyCode == Enum.KeyCode.ButtonL1 then
			alignposition.Enabled = true
		end
	end)
	
	uis.InputEnded:Connect(function(input, processed)
		if input.KeyCode == Enum.KeyCode.ButtonL1 then
			alignposition.Enabled = false
		end
	end)
end)

image

I just added a part that stays infront of your head and when you press L1 it enables the alignposition which sould make you fly towards it, this does not work

From the looks of your code, it’s due to you setting the CFrame. I suppose then it’s my mistake to give you the advice to use AlignPosition. Try this:

local HandVector = Hand.CFrame.LookVector
local newHeadCF = CFrame.new(HandVector) * HeadCFrame

Something like that might work.

alright, i wasnt sure what to do with this but i tried anyways

local uis = game:GetService("UserInputService")
local rs = game:GetService("RunService")
local vr = game:GetService("VRService")

local cc = workspace.CurrentCamera
local player = game.Players.LocalPlayer
local char = player.Character

local headscale = 1
local flying = false
local vrevent = game.ReplicatedStorage:WaitForChild("VREvent")

if vr.VREnabled == true then
	print(player.Name.." has VR enabled :)")
	vrevent:FireServer("Start")
else
	print(player.Name.." does not have VR enabled :(")
end

vrevent.OnClientEvent:Connect(function(vrModel)
	cc.HeadScale = headscale
	cc.CameraType = Enum.CameraType.Scriptable

	local clientModel = workspace:FindFirstChild(player.Name.."VRModel"):Clone()
	clientModel.Parent = workspace
	clientModel.Name = player.Name.."ClientVRModel"

	local highlight = Instance.new("Highlight")
	highlight.Parent = clientModel
	highlight.FillTransparency = 1
	highlight.OutlineTransparency = 0.7

	local head:Part = clientModel.Head
	local lefthand:Part = clientModel.LeftHand
	local rightHand:Part = clientModel.RightHand

	for i, v in pairs(clientModel:GetDescendants()) do
		if v:IsA("BasePart") and v ~= lefthand and v ~= rightHand then
			v.Transparency = 1
		elseif v:IsA("Decal") or v:IsA("Texture") then
			v.Transparency = 1
		end
	end

	vrModel:Destroy()

	vr:RecenterUserHeadCFrame()

	rs.RenderStepped:Connect(function()
		local headcframe = vr:GetUserCFrame(Enum.UserCFrame.Head)
		local lefthandcframe = vr:GetUserCFrame(Enum.UserCFrame.LeftHand)
		local righthandcframe = vr:GetUserCFrame(Enum.UserCFrame.RightHand)
		
		if flying then
			local HandVector = rightHand.CFrame.LookVector
			headcframe = CFrame.new(HandVector) * headcframe
		end

		head.CFrame = (cc.CFrame*CFrame.new(headcframe.Position*headscale))*CFrame.fromEulerAnglesXYZ(headcframe:ToEulerAnglesXYZ())
		lefthand.CFrame = (cc.CFrame*CFrame.new(lefthandcframe.Position*headscale))*CFrame.fromEulerAnglesXYZ(lefthandcframe:ToEulerAnglesXYZ())
		rightHand.CFrame = (cc.CFrame*CFrame.new(righthandcframe.Position*headscale))*CFrame.fromEulerAnglesXYZ(righthandcframe:ToEulerAnglesXYZ())

		cc.CFrame = headcframe

		vrevent:FireServer("Update", {
			vrModel = vrModel,
			headcframe = head.CFrame,
			lefthandcframe = lefthand.CFrame,
			righthandcframe = rightHand.CFrame
		})
	end)

	uis.InputBegan:Connect(function(input, processed)
		if input.KeyCode == Enum.KeyCode.ButtonL1 then
			flying = true
		end
	end)
	
	uis.InputEnded:Connect(function(input, processed)
		if input.KeyCode == Enum.KeyCode.ButtonL1 then
			flying = false
		end
	end)
end)

when i spawn and try to fly nothing happens, but when i switch to the server my bodyparts fly away, probably because they arent anchored though so not related

Why don’t you try setting cc.CFrame = headcframe before you set the head.CFrame?

You mean like this?

rs.RenderStepped:Connect(function()
		local headcframe = vr:GetUserCFrame(Enum.UserCFrame.Head)
		local lefthandcframe = vr:GetUserCFrame(Enum.UserCFrame.LeftHand)
		local righthandcframe = vr:GetUserCFrame(Enum.UserCFrame.RightHand)
		
		--moved this above the rest
		cc.CFrame = headcframe
		
		if flying then
			local HandVector = rightHand.CFrame.LookVector
			headcframe = CFrame.new(HandVector) * headcframe
		end

		head.CFrame = (cc.CFrame*CFrame.new(headcframe.Position*headscale))*CFrame.fromEulerAnglesXYZ(headcframe:ToEulerAnglesXYZ())
		lefthand.CFrame = (cc.CFrame*CFrame.new(lefthandcframe.Position*headscale))*CFrame.fromEulerAnglesXYZ(lefthandcframe:ToEulerAnglesXYZ())
		rightHand.CFrame = (cc.CFrame*CFrame.new(righthandcframe.Position*headscale))*CFrame.fromEulerAnglesXYZ(righthandcframe:ToEulerAnglesXYZ())

		vrevent:FireServer("Update", {
			vrModel = vrModel,
			headcframe = head.CFrame,
			lefthandcframe = lefthand.CFrame,
			righthandcframe = rightHand.CFrame
		})
	end)

nothing changes

if flying then
	local HandVector = rightHand.CFrame.LookVector
	headcframe = CFrame.new(HandVector) * headcframe
end
cc.CFrame = headcframe
1 Like

This did actually show some results, not flying but basically makes my camera move slightly in the direction my hand is pointing in, camera goes back to normal after I let go of the buttons

It moves slowly because you haven’t adjust speed properly. As for it moving back… I suggest having an external CFrame variable storing this.
So like:
– Fly CFrame
– Run Service loop.
– Main.

Can you elaborate on speed? Sorry if I sound absolutely stupid but I never tried making a vr system until yesterday

Just multiply the HandVector with some number as your speed.

Alright, I tried multiplying it by 10

local HandVector = rightHand.CFrame.LookVector * 10

But I’m still unable to move more then a certain amount depending on where my hand is facing

Let me double check, when we were trying body velocities I unanchored every part, do the parts still need to be unanchored now?

No, you don’t have to unanchor parts.

That’s because you didn’t follow the other instruction I gave which was to have an external variable store all the fly position and then you can add it to the head CFrame. Although, now you would have to add the HandVector to this new fly position variable.

I’m still not getting how I can do this, I tried putting a bunch of stuff together but obviously didn’t work

if flying then
	local HandVector = rightHand.CFrame.LookVector * 10
	headcframe = oldPos * (CFrame.new(HandVector) * headcframe)
	
	oldPos = headcframe
end

Never mind, I was able to figure it out using this tutorial.
Thank you for your help!