VR picking up object is weird

So I’ve been trying to make something in VR where you can pick up items, and I’ve been experimenting with this.
I’ve been trying to use BodyPositions, AlignPositions, etc, but I can’t seem to make it look good…
What happens:
https://gyazo.com/7d59f16c58d9e332a2d3eae4e3429de3
I’m using BodyPositions for this.
Code:

local UserInputService = game:GetService("UserInputService")
local StarterGUI = game:GetService("StarterGui")
local VRService = game:GetService("VRService")
local CurrentCamera = workspace.CurrentCamera
UserInputService.InputBegan:Connect(function(k)
	print((k.KeyCode == Enum.KeyCode.Unknown and "it dont have one tho") or k.KeyCode or "it dont have one tho")
end)
if VRService.VREnabled == true then
	warn("VR is enabled")
	repeat game:GetService("RunService").Heartbeat:Wait() local PCallSuccess = pcall(function() StarterGUI:SetCore("VRLaserPointerMode", 0) StarterGUI:SetCore("VREnableControllerModels", false) end) until PCallSuccess
	game.Players.LocalPlayer.CameraMaxZoomDistance = .5
	game.Players.LocalPlayer.CameraMode = Enum.CameraMode.LockFirstPerson
	local ReplicatedStorage = game:GetService("ReplicatedStorage")
	local Hands = ReplicatedStorage:WaitForChild("oculusHands"):Clone()
	local handL = Hands:WaitForChild("handL")
	local handR = Hands:WaitForChild("handR")
	local gripL = handL:WaitForChild("Grip")
	local gripR = handR:WaitForChild("Grip")
	local gripPalmL = gripL:WaitForChild("LeftHand"):WaitForChild("Palm")
	local gripPalmR = gripR:WaitForChild("RightHand"):WaitForChild("Palm")
	local handPalmL = handL:WaitForChild("LeftHand"):WaitForChild("Palm")
	local handPalmR = handR:WaitForChild("RightHand"):WaitForChild("Palm")
	local usingGrip = false
	Hands.Parent = workspace
	handL:SetPrimaryPartCFrame(VRService:GetUserCFrame(Enum.UserCFrame.LeftHand))
	handR:SetPrimaryPartCFrame(VRService:GetUserCFrame(Enum.UserCFrame.RightHand))
	local Focused = false
	UserInputService.TextBoxFocused:Connect(function() Focused = true end) UserInputService.TextBoxFocusReleased:Connect(function() Focused = false end)
	UserInputService.InputBegan:Connect(function(input)
		if not Focused then
			if input.KeyCode == Enum.KeyCode.ButtonB then
				VRService:RecenterUserHeadCFrame()
			elseif input.KeyCode == Enum.KeyCode.ButtonR1 then
				for _,v in pairs(workspace:GetDescendants()) do
					if v:IsA("BasePart") then
						if v:FindFirstChild("CanBePickedUp") and v:FindFirstChild("Attach") then
							if v:FindFirstChild("CanBePickedUp").Value == true then
								if v.Anchored == false then
									if (handR.PrimaryPart.CFrame.Position - v.CFrame.Position).Magnitude <= 5 then
										spawn(function()
											v.Position = handR.PrimaryPart.CFrame.Position + (handR.PrimaryPart.CFrame.UpVector)
											local attachmentToUse = ((usingGrip == true and gripPalmR) or (usingGrip == false and handPalmR))
											local CanCollide = v.CanCollide
											local PickedUp = true
											v.CanCollide = false
											local Align = Instance.new("BodyPosition", v)
											Align.MaxForce = Vector3.new(100000, 100000, 100000)
											Align.P = 100
											Align.D = 1
											local Connect
											Connect = UserInputService.InputEnded:Connect(function(input)
												if input.KeyCode == Enum.KeyCode.ButtonR1 then
													PickedUp = false
													Connect:Disconnect()
													return
												end
											end)
											repeat game:GetService("RunService").RenderStepped:Wait() Align.Position = (CurrentCamera.CFrame * VRService:GetUserCFrame(Enum.UserCFrame.RightHand)).Position + Vector3.new(0, 0, 2) until not PickedUp
											Align:Destroy()
											v.CanCollide = CanCollide
										end)
										break
									end
								end
							end
						end
					end
				end
			end
		end
	end)
	game:GetService("RunService").RenderStepped:Connect(function()
		handL:SetPrimaryPartCFrame((CurrentCamera.CFrame * VRService:GetUserCFrame(Enum.UserCFrame.LeftHand)) * CFrame.Angles(0, math.rad(180), math.rad(90)))
		handR:SetPrimaryPartCFrame((CurrentCamera.CFrame * VRService:GetUserCFrame(Enum.UserCFrame.RightHand)) * CFrame.Angles(0, math.rad(180), math.rad(90)))
	end)
else
	warn("VR is not enabled")
end

Anything that could help will be greatly appreciated!

7 Likes

Wow, that is some seriously deep nesting! I’d recommend combining all those if statements using and as well as breaking that key handler into a separate function.

It seems to me that the force is under dampened. Increasing the D parameter should help. The problem with using a force for this though is that the amount of force required to achieve the same movement behavior will change as the mass of the part increases. You could use the TweenService to tween between the current CFrame and goal CFrame regardless of mass.

4 Likes

I have increased the D parameter before and that just made it go slow motion. I’m trying to make it stay in the hand’s position while still having velocity to be able to throw it.

1 Like

Hehe, and moving slowly to the correct point would mean that the force is over dampened. There should be a sweet spot, although it may be difficult to find! Reaching that sweet spot makes the motion “critically dampened.” There should be a formula for critical dampening, although I’m not aware of what it is in this case. I’ll have to defer to the community for the formula.

1 Like

Yes, I get that, but I’m trying to make it instantly stick to the hand without any tweening/dampening, if you get me.

1 Like

Could you anchor it while picked up and unanchor it while not? Then you could just directly set the cframe each frame reliably.

As I said before, I’m trying to make it so it keeps the velocity of the cube when you’re moving your hand around, so when you let go, you can throw it.

Ah, yes, okay. You can simply set the CFrame then every renderstep. To set the velocity when the part is released, you simply have to keep track of the previous known positions over some time (like a tenth of a second). The averaged changes in position over time (weighted by how close they are in time to the actual moment of release) would give a nice velocity.

1 Like

I will try this and see if that works.

Store the cframe or position of the last few frames and you could calculate it. Ex lastframepos-thisframepos and just set the velocity (may need to multiply the above value by the mass for a effect).

If you are firm with bodyPositons, you will just have to find that sweet spot by tweaking values.

1 Like

What are the properties of the bodypositions?

Can you show me?

It’s already seen in the script.
Plus, I’ve moved on to CFrame editing.
I’m trying to get an equation to where I am able to make it throw good without it falling to the ground.
Current:

v.Velocity = (BeforePosition - v.Position) * 1.5
1 Like

Instead of using FindFirstChild, you should use HasTag as you will use less instances this way.

1 Like

Velocity is not a property of a bodyposition.

Unless my mind is fooling me?

I find it good to use a bool value because sometimes you can make an item that can be picked up at random times, and can be used for… let’s say, a random number generator.

As I said, I have moved onto CFrame editing, and am no longer using BodyPositions.

1 Like

Is the moveable brick anchored?

If not then I would consider anchoring it.

1 Like

Yes it is. Updated code:

for _,v in pairs(workspace:GetDescendants()) do
	if v:IsA("BasePart") then
		if v:FindFirstChild("CanBePickedUp") and v:FindFirstChild("Attach") then
			if v:FindFirstChild("CanBePickedUp").Value == true and v.Anchored == false and (handR.PrimaryPart.CFrame.Position - v.CFrame.Position).Magnitude <= 5 then
				spawn(function()
					v.Position = handR.PrimaryPart.CFrame.Position + (handR.PrimaryPart.CFrame.UpVector)
					local attachmentToUse = ((usingGrip == true and gripPalmR) or (usingGrip == false and handPalmR))
					local OrigLV = v.CFrame.LookVector
					local BeforePosition = v.Position
					local CanCollide = v.CanCollide
					local PickedUp = true
					v.CanCollide = false
					v.Anchored = true
					local Connect
					Connect = UserInputService.InputEnded:Connect(function(input)
						if input.KeyCode == Enum.KeyCode.ButtonR1 then
							PickedUp = false
							Connect:Disconnect()
							return
						end
					end)
					repeat game:GetService("RunService").RenderStepped:Wait() BeforePosition = v.Position / 1.2 v.CFrame = CFrame.new(handR.PrimaryPart.CFrame.Position - handR.PrimaryPart.CFrame.UpVector, OrigLV + handR.PrimaryPart.CFrame.UpVector) until not PickedUp
					v.CanCollide = CanCollide
					v.Anchored = false
					v.Velocity = (BeforePosition - v.Position) * 1.5
				end)
				break
			end
		end
	end
end
1 Like

Couldn’t you use RemoveTag in conjunction with AddTag?

If you need to know when an object has their tag removed or added, you can use GetInstanceRemovedSignal and GetInstanceAddedSignal respectively.

1 Like

I wouldn’t like to mess with CollectionService or whatever it is that uses the tags, because I am trying to keep this simplistic as I might release this as a free model.