The script I provided is incomplete, because although I could sit here and help you all night, and I mean that I definitely could, I would not be doing you any favors by just giving you the answers.
Let’s go over the first concept, you mentioned welding the arms to the controllers, and truthfully that’s an idea that in theory would work, you would be able to have the benefit of not having to script every single “grab” hand interaction since the object you’re grabbing could just be welded to the arm when grabbed, it would make for a cool experience seeing you characters arms as your own, and it would be the easiest way to go about it, but in order to do that you need to create proxies that would essentially be a representation of your controller identical in both orientation and position, and that’s just the tip of the iceberg because after you have those proxies, you would then need to update those proxies to match the real controllers, and weld them, but after all of that, you would still need to do the most important thing which is updating the CFrame of the player’s representation, and parts.
Now let’s review the alternative, look over the script I provided and I want you to look for the following:
Run.RenderStepped:Connect(function()
The function is one of the most important ones when creating a VR experience. In Unity developers use “void Update()” and I only bring that up because of the terminology, the word Update. We need to see what we are updating every frame. Run.RenderStepped runs every frame.
If we look at our script and locate Run.RenderStepped we see the following items on there:
Cam.HeadLocked = true
Cam.CameraType = Enum.CameraType.Scriptable
end)
local spawnPos = findSpawnLocation()
char:SetPrimaryPartCFrame(CFrame.new(spawnPos))
If we are keeping track of our problem, our problem is the head, and 2 arms that don’t seem to be Updated
It’s important to remember that any items that will be in constant motion, will need to be updated every frame, this can get resource intensive if you run everything the player sees using RunRenderStepped, so it’s important to plan your project accordingly.
If the play is to keep up with the player’s movements but you only update the camera, and not the arms, then your arms will stay behind since the only time we reference the player’s Primary Part CFrame is when we set CFrame.new to place the Player’s Primary part in spawnPos which is us running a function to location the Spawn Location, how is that function actually looking and finding the spawn location?
–First we declare the function findSpawnLocation
– Second we reference the location of the Spawn Location, followed by an if
– If we can’t find spawnLocationm then we look for the baseplate
– if a baseplate is found, then we spawn at 0,3,0, but if a baseplate is not found, or a spawnlocation, the we spawn a whopping 0,10,0 which is fairly high.
local function findSpawnLocation()
local spawnLocation = Workspace:FindFirstChild(“Spawn Location”)
if not spawnLocation then
local baseplate = Workspace:FindFirstChild(“Baseplate”)
if baseplate then
return baseplate.Position + Vector3.new(0, 3, 0)
end
else
return spawnLocation.Position
end
return Vector3.new(0, 10, 0)
end
Now that we’ve taken this time to get a bit of understanding for the amount of time and effort it takes to figure out the issues and how to overcome them, I will share the last script I will be sending you.
Before you copy, and paste the script, take 10 minutes to look at the full script, look at the references so that you get an idea for the things you need to have in your game, and what they need to be named.
If you truly want to develop a game and love the idea of it, make this your best friend: VRService | Documentation - Roblox Creator Hub
Best of luck!
local UIS = game:GetService(“UserInputService”)
local VRS = game:GetService(“VRService”)
local Run = game:GetService(“RunService”)
local SG = game:GetService(“StarterGui”)
local Workspace = game:GetService(“Workspace”)
local plr = game.Players.LocalPlayer
local char = script.Parent
local Cam = Workspace.CurrentCamera
local RightHand = char:WaitForChild(“Right Arm”)
local LeftHand = char:WaitForChild(“Left Arm”)
local Head = char:WaitForChild(“Head”)
local Head2 = Workspace.Head2
local RArm2 = Workspace.RightArm2
local LArm2 = Workspace.LeftArm2
local function findSpawnLocation()
local spawnLocation = Workspace:FindFirstChild(“Spawn Location”)
if not spawnLocation then
local baseplate = Workspace:FindFirstChild(“Baseplate”)
if baseplate then
return baseplate.Position + Vector3.new(0, 3, 0)
end
else
return spawnLocation.Position
end
return Vector3.new(0, 10, 0)
end
if VRS.VREnabled == true then
SG:SetCore(“VRLaserPointerMode”, 0)
SG:SetCore(“VREnableControllerModels”, false)
VRS:RecenterUserHeadCFrame()
Cam.HeadScale = 1
local function updateVRComponents()
Head2.CFrame = Cam.CFrame * VRS:GetUserCFrame(Enum.UserCFrame.Head)
RArm2.CFrame = Cam.CFrame * VRS:GetUserCFrame(Enum.UserCFrame.RightHand)
LArm2.CFrame = Cam.CFrame * VRS:GetUserCFrame(Enum.UserCFrame.LeftHand)
end
VRS.UserCFrameChanged:Connect(updateVRComponents)
Run.RenderStepped:Connect(function()
Cam.HeadLocked = true
Cam.CameraType = Enum.CameraType.Scriptable
updateVRComponents()
end)
local spawnPos = findSpawnLocation()
char:SetPrimaryPartCFrame(CFrame.new(spawnPos))
end