How to let the player pick up a box?

I would like to create a portal style puzzle game.
I want the player to be able to pick up a box and to put it on buttons.
I already have a script to detect when the player clicks on the box and fires a remote event:

local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:wait()
local Head = Character:WaitForChild("Head")
local Mouse = Player:GetMouse()

local PickUpEvent = ReplicatedStorage:WaitForChild("RemoteEvents"):WaitForChild("PickUpBox")
local MaxDistance = script.MaxDistance
local MinDistance = script.MinDistance

wait(1)

local function onInputBegan(input, gameProcessed)
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		local Target = Mouse.Target
		if Target then
			local Distance = Target.Position - Head.Position
			local IsABox = Target:FindFirstChild("BoxScript")
			if Distance.X <= MaxDistance.Value.X and Distance.Y <= MaxDistance.Value.Y and Distance.Z <= MaxDistance.Value.Z and Distance.X >= MinDistance.Value.X and Distance.Y >= MinDistance.Value.Y and Distance.Z >= MinDistance.Value.Z and IsABox then
				PickUpEvent:FireServer(Target.name)
				print("Fired server!!")
			end
		end
	end
end

UserInputService.InputBegan:Connect(onInputBegan)

I want the box to move with physics so it won’t go through walls.
I think i will need to use raycast, but i don’t know how…
Thank you!

1 Like

I’m not sure how are you trying to make the player grab the box, but I made something similar just using a BodyPosition.

local function GetRatio(Vector)
	return math.max(Vector.X, Vector.Y, Vector.Z)
end

if not Object:FindFirstChild("BodyPosition") then
	local BodyPosition = Instance.new("BodyPosition")
	BodyPosition.MaxForce = Vector3.new(90000, 90000, 90000)
	BodyPosition.P = 20000
	BodyPosition.Position = Mouse.Origin.Position + Mouse.Origin.LookVector * (GetRatio(Box.Size) + 2)
	BodyPosition.Parent = Box
else
	local BodyPosition = Object:FindFirstChild("BodyPosition")
	BodyPosition.Position = Mouse.Origin.Position + Mouse.Origin.LookVector * (GetRatio(Box.Size) + 2)
end
2 Likes

what is the “object” in the script?

1 Like

Same as box, I was changing names so you could understand easily, but I forgot to change those. By the way this is just an example.

if not Box:FindFirstChild("BodyPosition") then
	local BodyPosition = Instance.new("BodyPosition")
	BodyPosition.MaxForce = Vector3.new(90000, 90000, 90000)
	BodyPosition.P = 20000
	BodyPosition.Position = Mouse.Origin.Position + Mouse.Origin.LookVector * (GetRatio(Box.Size) + 2)
	BodyPosition.Parent = Box
else
	local BodyPosition = Box:FindFirstChild("BodyPosition")
	BodyPosition.Position = Mouse.Origin.Position + Mouse.Origin.LookVector * (GetRatio(Box.Size) + 2)
end
2 Likes

Ok so i found the way to do it !!
All boxes in the game MUST have a different name from each other
here is the script i put in the box:

local Box = script.Parent
local BodyPosition = Instance.new("BodyPosition")

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local PickUpEvent = ReplicatedStorage:WaitForChild("RemoteEvents"):WaitForChild("PickUpBox")

local function MoveBox(Player, Target, Origin)
	if Target == Box.Name then
		local function GetRatio(Vector)
			return math.max(Vector.X, Vector.Y, Vector.Z)
		end

		if not Box:FindFirstChild("BodyPosition") then
			BodyPosition.MaxForce = Vector3.new(90000, 90000, 90000)
			BodyPosition.P = 20000
			BodyPosition.Position = Origin.Position + Origin.LookVector * (GetRatio(Box.Size) + 4)
			BodyPosition.Parent = Box
		else
			BodyPosition.MaxForce = Vector3.new(90000, 90000, 90000)
			BodyPosition.Position = Origin.Position + Origin.LookVector * (GetRatio(Box.Size) + 4)
		end
	else
		BodyPosition.MaxForce = Vector3.new(0,0,0)
	end
end

PickUpEvent.OnServerEvent:Connect(MoveBox)

And here is the script i put in starter player scripts:

local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")

local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:wait()
local Head = Character:WaitForChild("Head")
local Mouse = Player:GetMouse()
local Target

local PickUpEvent = ReplicatedStorage:WaitForChild("RemoteEvents"):WaitForChild("PickUpBox")
local MaxDistance = script:WaitForChild("MaxDistance")
local MinDistance = script:WaitForChild("MinDistance")
local IsPickUp = script:WaitForChild("IsPickUp")

function onHeartbeat(step)
	if IsPickUp.Value == true then
		PickUpEvent:FireServer(Target.name, Mouse.Origin)
	end
end

local function onInputBegan(input, gameProcessed)
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		Target = Mouse.Target
		if Target then
			local Distance = Target.Position - Head.Position
			local IsABox = Target:FindFirstChild("BoxScript")
			if Distance.X <= MaxDistance.Value.X and Distance.Y <= MaxDistance.Value.Y and Distance.Z <= MaxDistance.Value.Z and Distance.X >= MinDistance.Value.X and Distance.Y >= MinDistance.Value.Y and Distance.Z >= MinDistance.Value.Z and IsABox then
				IsPickUp.Value = true
			end
		end
	end
end

local function onInputEnded(input, gameProcessed)
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		IsPickUp.Value = false
		PickUpEvent:FireServer(0, 0)
		Target = nil
	end
end

UserInputService.InputBegan:Connect(onInputBegan)
UserInputService.InputEnded:Connect(onInputEnded)
connection = RunService.Heartbeat:Connect(onHeartbeat)

Thanks for help Sarchyx !!

2 Likes

When I use this code, Line 16 of the script in the box says “attempt to index number with ‘Position’”. have found that this is because of “Origin.Position”, if you have any answers i would appreciate it.