VR physics arms

Hello! I am trying to make a VR hand movement system (similar to VR titles like Boneworks, Blade & Sorcery, etc.) using physics for environment interaction and object weights, but can’t figure out how I would make a part “target” a certain CFrame, and then move/rotate that part to that CFrame. My attempt to do this using AlignOrientation’s and AlignPositions did not work, and just left my arms on the ground doing nothing.

Code below:

player.CharacterAdded:Connect(function(char)
	char:WaitForChild("Humanoid")
	Arms.LeftArm = char:FindFirstChild("Left Arm")
	Arms.RightArm = char:FindFirstChild("Right Arm")
	
	Arms.LeftArm.CanCollide = true
	Arms.RightArm.CanCollide = true
	
	char.Torso["Left Shoulder"]:Destroy()
	char.Torso["Right Shoulder"]:Destroy()
	
	Arms.LAA = Instance.new("Attachment")
	Arms.RAA = Instance.new("Attachment")
	
	local posL = alignPosTemp:Clone()
	local rotL = alignRotTemp:Clone()
	posL.Attachment0 = Arms.LAA
	rotL.Attachment0 = Arms.LAA
	
	local posR = alignPosTemp:Clone()
	local rotR = alignRotTemp:Clone()
	posR.Attachment0 = Arms.RAA
	rotR.Attachment0 = Arms.RAA
	
	posL.Parent = Arms.LeftArm
	rotL.Parent = Arms.LeftArm
	
	posR.Parent = Arms.RightArm
	rotR.Parent = Arms.RightArm
	RunService:BindToRenderStep("Arms", 201, function()
		if Arms.checkArm("Left") then 
			Arms.LeftArm.LocalTransparencyModifier = 0 
		end
		if Arms.checkArm("Right") then 
			Arms.RightArm.LocalTransparencyModifier = 0 
		end
		local headCFrame = VRService:GetUserCFrame(Enum.UserCFrame.Head)
		local centerCFrame = headCFrame:ToObjectSpace(workspace.CurrentCamera:GetRenderCFrame())
		local leftHandCFrame = centerCFrame * VRService:GetUserCFrame(Enum.UserCFrame.LeftHand)
		local rightHandCFrame = centerCFrame * VRService:GetUserCFrame(Enum.UserCFrame.RightHand)
		Arms.LeftArm.AlignOrientation.CFrame = leftHandCFrame
		Arms.RightArm.AlignOrientation.CFrame = rightHandCFrame
		Arms.LeftArm.AlignPosition.Position = leftHandCFrame.Position
		Arms.RightArm.AlignPosition.Position = rightHandCFrame.Position
	end)
end)

I also tried this, but to no avail:

2 Likes

can you send screenshots of your hierarchy for your hands and the properties for both align orientation and align position?

Hierarchy for the hands uses the default Character “Left Arm” and “Right Arm”, and then changes the properties in the script

same with the AlignPosition and AlignOrientation except they’re set to OneAttachment mode

personally for me, i make a whole new part for the hands and put them outside the character. here is my hierarchy.

2023-12-26 22_44_13-vrtest457 - VRHandler - Roblox Studio


here is my code for the same problem.

local function createHand(handType: R_L_W?)
		if handType == "L" then
			local selectedHand = replicatedStorage.Resources.HandModels.LeftHandFolder.handL
			local handL = selectedHand:Clone()
			local attachment0 = Instance.new("Attachment")
			attachment0.Name = "Attachment0"
			attachment0.Parent = handL.glove
			handL.Parent = workspace.GameFolder.hands
			handL.CFrame = char.HumanoidRootPart.CFrame
			if isDebug then
				warn("CreateHand function called: handType = " .. handType)
			end
			print(handL)
			return handL
		elseif handType == "R" then
			local selectedHand = replicatedStorage.Resources.HandModels.RightHandFolder.handR
			local handR = selectedHand:Clone()
			handR.Parent = workspace.GameFolder.hands
			handR.CFrame = char.HumanoidRootPart.CFrame
			if isDebug then
				warn("CreateHand function called: handType =" .. handType)
			end
			return handR
		--[[
		elseif handType == "W" then
			local selectedHand = script:FindFirstChild("RightHand")
			local RightHand = selectedHand:Clone()
			RightHand.CFrame = char.HumanoidRootPart.CFrame
		--]]
		end
	end
	
	-- create the actual hands
	local handLeft = createHand("L")
	local handRight = createHand("R")
	
	-- move hands with collisions function
	local moveHands = function(part, move)
		if part == Enum.UserCFrame.LeftHand then
			local alignPosition = handLeft.glove:FindFirstChildOfClass("AlignPosition")
			alignPosition.Position = camera.CFrame.Position + move.Position
			local alignOrientation = handLeft.glove:FindFirstChildOfClass("AlignOrientation")
			alignOrientation.CFrame = (camera.CFrame * move) * CFrame.Angles(-90, -90, 0)
		elseif part == Enum.UserCFrame.RightHand then
			local alignPosition = handRight.glove:FindFirstChildOfClass("AlignPosition")
			alignPosition.Position = camera.CFrame.Position + move.Position

			local alignOrientation = handRight.glove:FindFirstChildOfClass("AlignOrientation")
			alignOrientation.CFrame = (camera.CFrame * move) * CFrame.Angles(-90, 90, 0)
		end
	end

VRService.UserCFrameChanged:Connect(moveHands)
2 Likes

Thank you! I modified it slightly to work with what i had, but it works great!

Arms.handLeft = nil
Arms.handRight = nil

local function checkHand(hand: R_L?)
	if hand == "R" then
		return Arms.handRight ~= nil
	elseif hand == "L" then
		return Arms.handLeft ~= nil
	end
end

local function createHand(handType: R_L_W?)
	if handType == "L" then
		if checkHand("L") then
			Arms.handLeft:Destroy()
		end
		local selectedHand = script.Hands.LeftArm
		local handL = selectedHand:Clone()
		handL.Parent = workspace.Hands
		handL.CFrame = char.HumanoidRootPart.CFrame
		return handL
	elseif handType == "R" then
		if checkHand("R") then
			Arms.handLeft:Destroy()
		end
		local selectedHand = script.Hands.RightArm
		local handR = selectedHand:Clone()
		handR.Parent = workspace.Hands
		handR.CFrame = char.HumanoidRootPart.CFrame
		return handR
	end
end

player.CharacterAdded:Connect(function(character)
	char = character
	Arms.handLeft = createHand("L")
	Arms.handRight = createHand("R")
end)
Arms.handLeft = createHand("L")
Arms.handRight = createHand("R")

local moveHands = function(part, move)
	if part == Enum.UserCFrame.LeftHand and checkHand("L") then
		local alignPosition = Arms.handLeft:FindFirstChildOfClass("AlignPosition")
		alignPosition.Position = camera.CFrame.Position + move.Position
		local alignOrientation = Arms.handLeft:FindFirstChildOfClass("AlignOrientation")
		alignOrientation.CFrame = (camera.CFrame * move) * CFrame.Angles(-90, -90, 0)
	elseif part == Enum.UserCFrame.RightHand and checkHand("R") then
		local alignPosition = Arms.handRight:FindFirstChildOfClass("AlignPosition")
		alignPosition.Position = camera.CFrame.Position + move.Position
		local alignOrientation = Arms.handRight:FindFirstChildOfClass("AlignOrientation")
		alignOrientation.CFrame = (camera.CFrame * move) * CFrame.Angles(-90, 90, 0)
	end
end

VRService.UserCFrameChanged:Connect(moveHands)

great! glad i could help you! also, the cframe angles at the end of the orientation is meant for my gloves in game, due to the rotation being off. you should change those values and not your hand’s starting orientation.

2 Likes

I used the CFrame.Angles i already had before :+1:

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.