For some reason objects are too heavy, the movement joystick is not showing either.
The user should be able to drag the part and move around with it.
here is my script:
-- Dependencies:
local replicatedStorage = game:GetService("ReplicatedStorage")
local contextActionService = game:GetService("ContextActionService")
local runService = game:GetService("RunService")
local players = game:GetService("Players")
local userInputService = game:GetService("UserInputService")
local clientModules = replicatedStorage.Modules.Client
local dragController = require(clientModules.DragController)
local inputTypeDetector = require(clientModules.InputTypeDetector)
local localPlayer = players.LocalPlayer
local control
local baseCamera
coroutine.wrap(function()
local playerModule = localPlayer.PlayerScripts:WaitForChild("PlayerModule")
control = require(playerModule):GetControls()
baseCamera = require(playerModule:WaitForChild("CameraModule"):WaitForChild("BaseCamera"))
end)()
-- Paths:
local network = replicatedStorage.Network
local requestDrag = network.RequestDrag
local dragCancelled = network.DragCancelled
-- Data:
local inputTypes = inputTypeDetector.InputTypes
local target
local hit
-- Configuration:
local MAX_GRAB_DISTANCE = 10
-- Main:
contextActionService:BindAction("Drag", function(name, state, input)
if state == Enum.UserInputState.Begin then
if dragController.IsDragging then return Enum.ContextActionResult.Pass end
-- Get head
local character = localPlayer.Character
if character == nil then return Enum.ContextActionResult.Pass end
local head = character:FindFirstChild("Head")
if head == nil then return Enum.ContextActionResult.Pass end
-- Get target
local inputType = inputTypeDetector.GetInputType()
if inputType == inputTypes.KeyboardAndMouse or inputType == inputTypes.Gamepad then
if target == nil or hit == nil then return Enum.ContextActionResult.Pass end
elseif inputType == inputTypes.Touch then
if input.UserInputType ~= Enum.UserInputType.Touch then return Enum.ContextActionResult.Pass end
local inputPosition = input.Position
local screenPointRay = workspace.CurrentCamera:ScreenPointToRay(inputPosition.X, inputPosition.Y)
local extendedRay = Ray.new(screenPointRay.Origin, screenPointRay.Direction * 1000)
target, hit = workspace:FindPartOnRay(extendedRay, localPlayer.Character, false, true)
end
-- Check if can drag
if not dragController.CanDrag(target) then return Enum.ContextActionResult.Pass end
if (head.Position - hit).Magnitude > MAX_GRAB_DISTANCE then return Enum.ContextActionResult.Pass end
-- Prepare if touch
if inputType == inputTypes.Touch then
control:Disable()
end
-- Drag
dragController.Drag(target, hit)
-- Register drag on server
local wasCancelled = false
local connection
connection = dragController.DragCancelled:Connect(function()
connection:Disconnect()
wasCancelled = true
if inputType ~= inputTypes.Touch then return end
control:Enable()
end)
local isSuccessful = requestDrag:InvokeServer(target)
if wasCancelled or isSuccessful then return end
dragController.CancelDrag()
else
if state == Enum.UserInputState.End then
dragController.CancelDrag()
end
return Enum.ContextActionResult.Pass
end
end, false, Enum.UserInputType.MouseButton1, Enum.UserInputType.Touch, Enum.KeyCode.ButtonR2)
while true do
local inputType = inputTypeDetector.GetInputType()
if inputType == inputTypes.KeyboardAndMouse or inputType == inputTypes.Gamepad then
local location = userInputService:GetMouseLocation()
local viewportPointRay = workspace.CurrentCamera:ViewportPointToRay(location.X, location.Y)
local extendedRay = Ray.new(viewportPointRay.Origin, viewportPointRay.Direction * 1000)
target, hit = workspace:FindPartOnRay(extendedRay, localPlayer.Character, false, true)
end
runService.Heartbeat:Wait()
end
next script
-- ServerScriptService > Scripts > Draghandler
--draghandler
-- dependencies:
local replicatedStorage = game:GetService("ReplicatedStorage")
local serverScriptService = game:GetService("ServerScriptService")
local dragController = require(serverScriptService.Modules.DragController)
-- paths:
local network = replicatedStorage.Network
local requestDrag = network.RequestDrag
local dragCancelled = network.DragCancelled
-- main:
function requestDrag.OnServerInvoke(player, part)
if not dragController.CanDrag(player, part) then return false end
dragController.Drag(player, part)
return true
end
dragCancelled.OnServerEvent:Connect(function(player)
-- TODO
end)
next
-- ServerScriptService > Modules (folder) > DragController (module script)
--dragcontroller script
-- dependencies:
local players = game:GetService("Players")
local collectionService = game:GetService("CollectionService")
-- data:
local playerToDragData = {}
-- DragController:
local module = {}
function module.Drag(player, part)
assert(typeof(player) == "Instance" and player:IsA("Player"), "bad argument #1 to DragController.Drag, expects Instance<Player>")
assert(module.CanDrag(player, part), "bad argument #2 to DragController.Drag, expects part that can be dragged")
part:SetNetworkOwner(player)
end
function module.CanDrag(player, part)
assert(typeof(player) == "Instance" and player:IsA("Player"), "bad argument #1 to DragController.CanDrag, expects Instance<Player>")
if module.IsDragging(player) then return false end
if typeof(part) ~= "Instance" then return false end
if not part:FindFirstChild("Configuration") then return false end -- Check if part has a Configuration child
local owner = part.Owner.Value
if owner ~= 0 and owner ~= player.UserId then return false end -- TODO: add player whitelist checks
return true
end
function module.IsDragging(player)
assert(typeof(player) == "Instance" and player:IsA("Player"), "bad argument #1 to DragController.IsDragging, expects Instance<Player>")
local dragData = playerToDragData[player]
if dragData == nil then return end
return dragData.IsDragging
end
-- main:
players.PlayerAdded:Connect(function(player)
playerToDragData[player] = {
IsDragging = false,
}
end)
players.PlayerRemoving:Connect(function(player)
playerToDragData[player] = nil
end)
return module
next
--ReplicatedStorage > Modules > Client > InputTypeDetector
-- dependencies:
local userInputService = game:GetService("UserInputService")
-- enums
local inputTypes = {
KeyboardAndMouse = 1,
Gamepad = 2,
Touch = 3,
}
-- data:
local inputTypeToEnumMap = {
[Enum.UserInputType.MouseButton1] = inputTypes.KeyboardAndMouse,
[Enum.UserInputType.MouseButton2] = inputTypes.KeyboardAndMouse,
[Enum.UserInputType.MouseButton3] = inputTypes.KeyboardAndMouse,
[Enum.UserInputType.MouseWheel] = inputTypes.KeyboardAndMouse,
[Enum.UserInputType.MouseMovement] = inputTypes.KeyboardAndMouse,
[Enum.UserInputType.Keyboard] = inputTypes.KeyboardAndMouse,
[Enum.UserInputType.Touch] = inputTypes.Touch,
[Enum.UserInputType.Gamepad1] = inputTypes.Gamepad,
[Enum.UserInputType.Gamepad2] = inputTypes.Gamepad,
[Enum.UserInputType.Gamepad3] = inputTypes.Gamepad,
[Enum.UserInputType.Gamepad4] = inputTypes.Gamepad,
[Enum.UserInputType.Gamepad5] = inputTypes.Gamepad,
[Enum.UserInputType.Gamepad6] = inputTypes.Gamepad,
[Enum.UserInputType.Gamepad7] = inputTypes.Gamepad,
[Enum.UserInputType.Gamepad8] = inputTypes.Gamepad,
}
local inputType = inputTypeToEnumMap[userInputService:GetLastInputType()] or inputTypes.KeyboardAndMouse
local inputTypeChangedBindable = Instance.new("BindableEvent")
-- ClientUtil:
local module = {}
function module.GetInputType()
return inputType
end
module.InputTypeChanged = inputTypeChangedBindable.Event
module.InputTypes = inputTypes
-- main:
userInputService.LastInputTypeChanged:Connect(function(newInputType)
local enum = inputTypeToEnumMap[newInputType]
if enum == nil then return end
if enum == inputType then return end
inputType = enum
inputTypeChangedBindable:Fire(inputType)
end)
return module
next
--Replicatedstorage > Modules > client > Dragcontroller
-- dependencies:
local runService = game:GetService("RunService")
local collectionService = game:GetService("CollectionService")
local userInputService = game:GetService("UserInputService")
local players = game:GetService("Players")
local localPlayer = players.LocalPlayer
local playerScripts = localPlayer.PlayerScripts
local baseCamera
coroutine.wrap(function()
baseCamera = require(playerScripts:WaitForChild("PlayerModule"):WaitForChild("CameraModule"):WaitForChild("BaseCamera"))
end)()
-- paths:
local holdTarget = script.HoldTarget
local holdPositionAlignment = script.HoldPositionAlignment
local logic = workspace.Logic
-- data:
local holdGrip = Instance.new("Attachment")
local dragCancelledBindable = Instance.new("BindableEvent")
local draggedBindable = Instance.new("BindableEvent")
local currentHoldGrip
local heldPart
-- configuration:
local DRAG_DISTANCE = 10
-- DragController:
local module = {}
function module.CancelDrag()
if not module.IsDragging then return end
currentHoldGrip:Destroy()
currentHoldGrip = nil
holdPositionAlignment.Attachment0 = nil
heldPart = nil
module.IsDragging = false
dragCancelledBindable:Fire()
end
function module.Drag(part, position)
assert(module.CanDrag(part), "bad argument #1 to DragController.Drag, expects part that can be dragged")
assert(typeof(position) == "Vector3" or position == nil, "bad argument #2 to DragController.Drag, expects Vector3?")
if position == nil then
position = Vector3.new()
end
local cFrame = CFrame.new(position)
module.IsDragging = true
heldPart = part
currentHoldGrip = holdGrip:Clone()
currentHoldGrip.Position = part.CFrame:ToObjectSpace(cFrame).Position
currentHoldGrip.Parent = heldPart
holdPositionAlignment.Attachment0 = currentHoldGrip
holdTarget.CFrame = cFrame
draggedBindable:Fire(part, position)
end
function module.CanDrag(part)
if module.IsDragging then return false end
if typeof(part) ~= "Instance" then return false end
if not collectionService:HasTag(part, "Draggable") then return false end
local owner = part.Owner.Value
if owner ~= 0 and owner ~= localPlayer.UserId then return false end -- TODO: add player whitelist checks
return true
end
module.IsDragging = false
module.Dragged = draggedBindable.Event
module.DragCancelled = dragCancelledBindable.Event
-- main:
holdGrip.Visible = true
holdPositionAlignment.Parent = logic
holdTarget.Parent = logic
local function merge(a1, a2)
for _, v2 in ipairs(a2) do
table.insert(a1, v2)
end
return a1
end
coroutine.wrap(function()
while true do
if module.IsDragging and baseCamera ~= nil then
-- get necessary data
local subjectPosition = baseCamera:GetSubjectPosition()
if subjectPosition == nil then return end
-- get hit
local location = userInputService:GetMouseLocation()
local viewportPointRay = workspace.CurrentCamera:ViewportPointToRay(location.X, location.Y)
local rayOrigin = viewportPointRay.Origin
local mousePosition = CFrame.new(rayOrigin, rayOrigin + viewportPointRay.Direction):ToWorldSpace(CFrame.new(0, 0, -1000)).Position
local targetPosition = CFrame.new(subjectPosition, mousePosition):ToWorldSpace(CFrame.new(0, 0, -DRAG_DISTANCE)).Position
holdTarget.CFrame = CFrame.new(targetPosition)
end
runService.Heartbeat:Wait()
end
end)()
return module
Can someone help with this please. I cannot figure it out.