I have been working on a barebones R6 VR that uses the players character model (basically just want moving arms and head attached to a normal R6 body), but I came across an issue I still couldn’t find out after two months.
I am attempting to keep the VR players humanoid rootpart / Torso under the VR cameras head by using a calculated distance between the VR headsets current and last frame.
After applying that, I realized that moving the rootpart also moved the camera, causing the camera and rootpart to move at different speeds.
To fix this I tried to make the camera scriptable and change its subject to the head that way this wouldn’t happen, but of course as the scripter contract goes “fixing a bug can cause many more to arise.” Sure the rootpart now properly follows the head but now the body can roam free like a zombie.
Here is (yes my entire) code if you wanna use it for something go ahead VR needs more love.
local player = game.Players.LocalPlayer
local character = script.Parent
local module = require(character.SNVRCONFIG)
-------------
local oldpos = Vector3.new()
local currentpos = Vector3.new()
-------------
local camera = workspace.CurrentCamera
local humanoid = character:WaitForChild('Humanoid')
local root = character:WaitForChild('HumanoidRootPart')
local torso = character:WaitForChild('Torso')
local leftarm = character:WaitForChild('Left Arm')
local rightarm = character:WaitForChild('Right Arm')
local head = character:WaitForChild('Head')
local RNS = game:GetService("RunService")
local vrsrvice = game:GetService('VRService')
local vrstatus = game:GetService('VRStatusService')
if vrsrvice.VREnabled == true then
print(character, "IS in VR")
local function PreparePlayerForVR()
camera.CameraType = Enum.CameraType.Scriptable
--camera.HeadLocked = false
print('Initializing VR')
camera.CFrame = root.CFrame * module.bodyoffset
--vrsrvice.AutomaticScaling = Enum.VRScaling.World
vrsrvice.FadeOutViewOnCollision = true
--vrsrvice.ThirdPersonFollowCamEnabled = false
leftarm.Massless = true
rightarm.Massless = true
head.CanCollide = false --for now have it like this until you can find out how to have the head and torso specifically not be able to collide with each other
torso['Left Shoulder'].Enabled = false
torso['Right Shoulder'].Enabled = false --disable the attatchments so they cannot be animated
torso['Neck'].Enabled = false
player.CameraMaxZoomDistance = 0
player.CameraMinZoomDistance = 0
camera.CameraSubject = head
print('Camera Subject:', camera.CameraSubject)
if module.VRvisibilitymode == 'FullBody' then
for i, child in pairs(character:GetChildren()) do
if child:IsA('BasePart') then
wait(0.1)
child.LocalTransparencyModifier = child.Transparency
child:GetPropertyChangedSignal('LocalTransparencyModifier'):Connect(function()
--if child.Name ~= head then
child.LocalTransparencyModifier = child.Transparency
--end
end)
end
end
elseif module.VRvisibilitymode == 'Rec' then
for i, child in pairs(character:GetChildren()) do
if child:IsA('BasePart') and child.Name ~= 'Left Leg' and child.Name ~= 'Right Leg' and child.Name ~= 'Torso' then
wait(0.1)
child.LocalTransparencyModifier = child.Transparency
child:GetPropertyChangedSignal('LocalTransparencyModifier'):Connect(function()
--if child.Name ~= head then
child.LocalTransparencyModifier = child.Transparency
--end
end)
end
end
end
end
PreparePlayerForVR()
local function VRUPD(Determination : number)
camera = workspace.CurrentCamera
--print(camera.CFrame)
camera.HeadScale = module.headsize
--print(Determination)
--[[ Get the players headset and controllers]]--
local Headset = vrsrvice:GetUserCFrame(Enum.UserCFrame.Head)
local leftcontroller = vrsrvice:GetUserCFrame(Enum.UserCFrame.LeftHand)
local rightcontroller = vrsrvice:GetUserCFrame(Enum.UserCFrame.RightHand)
local floor = vrsrvice:GetUserCFrame(Enum.UserCFrame.Floor)
----------------------------------------------------------------------
--[[define the offsets and stuff like that]]--
local rotationoffset = module.rotationoffset
local offset = module.armsoffset
--------------------------------------------------------------------------
currentpos = Headset.Position --The current position of the head
local difference = currentpos - oldpos --This is the difference in position from the last frame to this one
--print(difference.Magnitude)
oldpos = currentpos --make the old position take over the new one
leftarm.CFrame = camera.CFrame * leftcontroller * offset * rotationoffset
rightarm.CFrame = camera.CFrame * rightcontroller * offset * rotationoffset
head.CFrame = camera.CFrame * Headset
--vrsrvice:RecenterUserHeadCFrame()
local cdiff = CFrame.new(difference)
root.CFrame = cdiff * root.CFrame --keeps the players body under the head
----------A bunch of failed attempts to make the camera move with the body without going back to square one----
-- local currentcam = camera.CFrame.Position
--local newcam = currentcam - cdiff
--camera.CFrame = root.CFrame * module.bodyoffset * cdiff
--camera.CFrame = root.CFrame * module.bodyoffset
--camera.CFrame = camera.CFrame - Vector3.new(cdiff, cdiff, cdiff)
-------------------------------------------------------------------------------------------------------------------
end
vrconnect = RNS.RenderStepped:Connect(VRUPD)
local function vrplayerdied()
vrconnect:Disconnect()
leftarm.Massless = false
rightarm.Massless = false
head.CanCollide = true
torso['Left Shoulder'].Enabled = true
torso['Right Shoulder'].Enabled = true
torso['Neck'].Enabled = true
end
humanoid.Died:connect(vrplayerdied)
else
print(character, 'Is NOT in vr')
end
-- remember to dont let players be able to stick their heads through walls, just have it push them back