So I’m creating a very basic VR system using Nexus VR as a base. I’ve gotten the basics of grabbing objects down, using AlignPositions and AlignOrientations to allow the object to move towards the hand but still be both unable to go through walls and able to be thrown.
I’d like to implement a system where an object can be held with two hands, using a second attachment for second hand placement. My idea was to apply two different AlignPositions and disable the AlignOrientations, so the attachments would move to each hand without disrupting the other’s by trying to align rotation. However, it doesn’t seem to work like this, and instead the object just gets stuck in the first hand and then flops over as if it was a BallSocket. So how would I go about moving the part in such a way that both hands are attached?
The following script has a lot of parts, so I’ll spoiler it to not flood the post too much.
GrabScript
local plr = game.Players.LocalPlayer
local char = plr.Character
local handhitbox = game.ReplicatedStorage.VR.HandHitbox
local lefthand
local righthand
local leftweld
local rightweld
local leftweldrot
local rightweldrot
local runServ = game:GetService("RunService")
local contextServ = game:GetService("ContextActionService")
function init()
-- Setup the Hand Hitboxes
lefthand = handhitbox:Clone()
lefthand.Name = 'LHandHitbox'
lefthand.Parent = char
righthand = handhitbox:Clone()
righthand.Name = 'RHandHitbox'
righthand.Parent = char
-- Now setup welds used for grabbin.
leftweld = Instance.new("AlignPosition", char:FindFirstChild('LeftHand').LeftGripAttachment)
leftweld.Attachment1 = leftweld.Parent
leftweld.Responsiveness = 50
leftweldrot = Instance.new("AlignOrientation", char:FindFirstChild('LeftHand').LeftGripAttachment)
leftweldrot.Attachment1 = leftweld.Parent
leftweldrot.Responsiveness = 50
rightweld = Instance.new("AlignPosition", char:FindFirstChild('RightHand').RightGripAttachment)
rightweld.Attachment1 = rightweld.Parent
rightweld.Responsiveness = 50
rightweldrot = Instance.new("AlignOrientation", char:FindFirstChild('RightHand').RightGripAttachment)
rightweldrot.Attachment1 = rightweld.Parent
rightweldrot.Responsiveness = 50
-- Roblox jank fix
righthand.Touched:Connect(function() end)
lefthand.Touched:Connect(function() end)
end
runServ.RenderStepped:Connect(function()
-- Update Hand Position
local lhandpos = char:FindFirstChild("LeftHand").CFrame
local rhandpos = char:FindFirstChild("RightHand").CFrame
lefthand.CFrame = lhandpos
righthand.CFrame = rhandpos
end)
function grabbity(hand)
local weld
local rotweld
local otherweld
local otherrotweld
-- Incredibly unreadable because i like compactness >_<
if hand == righthand then rotweld = rightweldrot weld = rightweld otherweld = leftweld otherrotweld = leftweldrot
else weld = leftweld rotweld = leftweldrot otherweld = rightweld otherrotweld = rightweldrot end
-- Find the stuff touching the hand hitbox
for i, v in pairs(hand:GetTouchingParts()) do
if v:FindFirstChild('GrabObj') then
local grabclass = require(v:FindFirstChild('GrabObj'))
local target = grabclass[1]
if otherweld.Attachment0 and otherweld.Attachment0.Parent == v and otherweld.Attachment0 ~= grabclass[2] then
-- Change to the second weld if the first one is taken by the other hand.
target = grabclass[2]
rotweld.Enabled = false
otherrotweld.Enabled = false
end
-- Weld it up, then break so that you dont loop through parts unnescesarily (dont worry i can speling)
weld.Attachment0 = target or v:FindFirstChild('Grab')
rotweld.Attachment0 = target or v:FindFirstChild('Grab')
break
end
end
end
function release(hand)
local weld
local rotweld
local otherweld
local otherrotweld
-- Incredibly unreadable because i like compactness >_<
if hand == righthand then rotweld = rightweldrot weld = rightweld otherweld = leftweld otherrotweld = leftweldrot
else weld = leftweld rotweld = leftweldrot otherweld = rightweld otherrotweld = rightweldrot end
weld.Attachment0 = nil
rotweld.Attachment0 = nil
rotweld.Enabled = true
otherrotweld.Enabled = true
end
local function grab(str, inputState, inputObj)
-- Check input
if inputState == Enum.UserInputState.Begin then
if inputObj.KeyCode == Enum.KeyCode.ButtonR1 then
grabbity(righthand)
elseif inputObj.KeyCode == Enum.KeyCode.ButtonL1 then
grabbity(lefthand)
end
elseif inputState == Enum.UserInputState.End then
if inputObj.KeyCode == Enum.KeyCode.ButtonR1 then
release(righthand)
elseif inputObj.KeyCode == Enum.KeyCode.ButtonL1 then
release(lefthand)
end
end
end
contextServ:BindAction("GrabL", grab, false, Enum.KeyCode.ButtonL1, Enum.KeyCode.ButtonR1)
init()