im making a VR script for grabbing and holding items.
keep getting the error “invalid argument #2 (Vector3 expected, got CFrame)”
ServerScript:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
-- RemoteEvent for handling grab/release requests
local grabRemote = Instance.new("RemoteEvent")
grabRemote.Name = "GrabRemote"
grabRemote.Parent = ReplicatedStorage
-- Keeps track of the grabbed objects
local grabbedObjects = {}
-- Handles grab/release requests from clients
grabRemote.OnServerEvent:Connect(function(player, action, object, hand, position, rotation)
if action == "Grab" and object:IsA("BasePart") then
object:SetNetworkOwner(player)
object.Anchored = false -- Ensure it remains unanchored
grabbedObjects[object] = true
print(player.Name .. " grabbed object:", object.Name)
elseif action == "Release" and object:IsA("BasePart") then
object.Anchored = false
object:SetNetworkOwner(nil)
grabbedObjects[object] = nil
print(player.Name .. " released object:", object.Name)
elseif action == "Update" and object:IsA("BasePart") and grabbedObjects[object] then
-- Update the object's CFrame based on position and rotation
object.CFrame = CFrame.new(position) * CFrame.Angles(math.rad(rotation.X), math.rad(rotation.Y), math.rad(rotation.Z))
end
end)
LocalScript in StarterPlayerScripts
-- LocalScript: StarterPlayerScripts/VRGrabScript
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local Workspace = game:GetService("Workspace")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local player = Players.LocalPlayer
local grabbing = false
local grabbedObject = nil
local grabDistance = 3 -- Adjust based on how far you want the user to reach
local currentHand = nil
-- RemoteEvent for requesting grab/release
local grabRemote = ReplicatedStorage:WaitForChild("GrabRemote")
-- Function to handle grabbing objects
local function grabObject(hand)
if grabbing then
return
end
currentHand = hand
local handCFrame = UserInputService:GetUserCFrame(hand)
local cameraCFrame = Workspace.CurrentCamera.CFrame
local handWorldCFrame = cameraCFrame * handCFrame
local handWorldPosition = handWorldCFrame.Position
for _, part in pairs(Workspace.CanGrab:GetChildren()) do
if part:IsA("BasePart") then
local distance = (part.Position - handWorldPosition).Magnitude
if distance <= grabDistance then
grabbing = true
grabbedObject = part
grabRemote:FireServer("Grab", part, hand, handWorldPosition, handWorldCFrame) -- Pass handWorldCFrame to server
print("Request to grab object:", part.Name)
break
end
end
end
end
-- Function to handle releasing objects
local function releaseObject()
if not grabbing then
return
end
grabbing = false
grabRemote:FireServer("Release", grabbedObject)
grabbedObject = nil
currentHand = nil
print("Request to release object")
end
-- Input listener for VR controller
UserInputService.InputBegan:Connect(function(input, processed)
if processed then return end
if input.UserInputType == Enum.UserInputType.Gamepad1 then
if input.KeyCode == Enum.KeyCode.ButtonR2 then
grabObject(Enum.UserCFrame.RightHand)
elseif input.KeyCode == Enum.KeyCode.ButtonL2 then
grabObject(Enum.UserCFrame.LeftHand)
end
end
end)
UserInputService.InputEnded:Connect(function(input, processed)
if processed then return end
if input.UserInputType == Enum.UserInputType.Gamepad1 then
if input.KeyCode == Enum.KeyCode.ButtonR2 and currentHand == Enum.UserCFrame.RightHand then
releaseObject()
elseif input.KeyCode == Enum.KeyCode.ButtonL2 and currentHand == Enum.UserCFrame.LeftHand then
releaseObject()
end
end
end)
-- Continuously update the position and rotation of the grabbed object
RunService.RenderStepped:Connect(function()
if grabbing and grabbedObject then
local handCFrame = UserInputService:GetUserCFrame(currentHand)
local cameraCFrame = Workspace.CurrentCamera.CFrame
local handWorldCFrame = cameraCFrame * handCFrame
local handWorldPosition = handWorldCFrame.Position
local relativeRotation = (cameraCFrame - handWorldCFrame).LookVector
-- Convert relative rotation to Euler angles
local rotationX = math.deg(math.atan2(-relativeRotation.Y, -relativeRotation.Z))
local rotationY = math.deg(math.atan2(relativeRotation.X, math.sqrt(relativeRotation.Y^2 + relativeRotation.Z^2)))
local rotationZ = 0 -- We assume no roll for simplicity
-- Convert handWorldPosition to Vector3
handWorldPosition = Vector3.new(handWorldPosition.X, handWorldPosition.Y, handWorldPosition.Z)
grabRemote:FireServer("Update", grabbedObject, handWorldPosition, Vector3.new(rotationX, rotationY, rotationZ))
end
end)