-
What do you want to achieve? Keep it simple and clear!
I want to fix the really irritating jitter caused when grabbing stuff -
What is the issue? Include screenshots / videos if possible!
Whenever trying to grab an object (whether you have network ownership or not) AlignPosition causes this really awkward and bad looking jitter -
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
Haven’t tried any solutions because I don’t even know the root cause of this (as you can see by the cubes, everything is being positioned properly). I don’t think anybody else has had this
Red Cube = Mouse’s direction multiplied by distance (distance variable is how far out a held object should be which is why the mouse looks so close. It’s not holding anything so distance is 0)
Green Cube = The closest point to the mouse position found on the surface of the object trying to be grabbed
There’s this disgusting looking jitter whenever a player grabs objects and it’s always on the same axis (-X axis) and mostly always by the same amount. I have literally no idea what’s causing this and it isn’t the visual representations because they have cancollide, cantouch and canquery off. One thing I’ve noted is the less maxforce there is the less the jitter is which I suppose could be expected. Dropped the code below. This should be all you need because the server does nothing with the grab except give the player network ownership of the part
For the record I’m completely aware how abysmal this script might look in some areas. I have yet to refactor it because tinkering with the grabbing has been taking up all the time
local humanoid = script.Parent:FindFirstChildOfClass("Humanoid")
local mouse = game:GetService("Players").LocalPlayer:GetMouse()
local getOwner = game:GetService("ReplicatedStorage").GetNetworkOwner
local requestGrab = game:GetService("ReplicatedStorage").Grab
local unGrab = game:GetService("ReplicatedStorage").UnGrab
local target = nil
local rootParent = nil
local targetAttachment = nil
local targetPosition = nil
local distance = 0
local maxDist = 15
local grabOffset = 1.5
local pull = false
local push = false
local function SetupGrabbing()
targetAttachment = Instance.new("Attachment")
targetAttachment.Parent = target
targetAttachment.WorldPosition = target:GetClosestPointOnSurface(mouse.Hit.Position)
distance = math.clamp(((humanoid.RootPart.Position + Vector3.yAxis * grabOffset) - targetAttachment.WorldPosition).Magnitude, 0, maxDist)
targetPosition = Instance.new("AlignPosition")
targetPosition.Parent = target
targetPosition.Mode = Enum.PositionAlignmentMode.OneAttachment
targetPosition.Attachment0 = targetAttachment
targetPosition.MaxForce = 100000
targetPosition.ForceRelativeTo = Enum.ActuatorRelativeTo.World
targetPosition.Responsiveness = 50
end
local function DestroyGrabbing()
target = nil
rootParent = nil
if targetAttachment then
targetAttachment:Destroy()
end
targetPosition = nil
distance = 0
unGrab:FireServer()
end
local function WeldToSurroundingObjects()
if target then
if game:GetService("ReplicatedStorage").Weld:InvokeServer() == true then
DestroyGrabbing()
end
end
end
mouse.Button1Down:Connect(function()
if mouse.Target and mouse.Target:HasTag("Grabbable") and (mouse.Hit.Position - humanoid.RootPart.Position).Magnitude <= maxDist then
local result = requestGrab:InvokeServer(mouse.Target)
if result then
target = mouse.Target
rootParent = RecursiveParent(target)
SetupGrabbing()
else
DestroyGrabbing()
end
end
end)
mouse.Button1Up:Connect(function()
DestroyGrabbing()
end)
game:GetService("UserInputService").InputBegan:Connect(function(input, gameProcessedThis)
if target and not gameProcessedThis then
if input.KeyCode == Enum.KeyCode.F then
WeldToSurroundingObjects()
elseif input.KeyCode == Enum.KeyCode.Q then
pull = true
elseif input.KeyCode == Enum.KeyCode.E then
push = true
end
end
end)
game:GetService("UserInputService").InputEnded:Connect(function(input)
if input.KeyCode == Enum.KeyCode.Q then
pull = false
elseif input.KeyCode == Enum.KeyCode.E then
push = false
end
end)
game:GetService("RunService").RenderStepped:Connect(function(dt)
workspace.Part.Position = (humanoid.RootPart.Position + Vector3.yAxis * grabOffset) + mouse.UnitRay.Direction * distance
if target and targetAttachment and targetPosition then
workspace.Part2.Position = targetAttachment.WorldPosition
targetPosition.Position = (humanoid.RootPart.Position + Vector3.yAxis * grabOffset) + mouse.UnitRay.Direction * distance
if (targetAttachment.WorldPosition - humanoid.RootPart.Position).Magnitude > maxDist then
DestroyGrabbing()
end
if pull then
distance = math.clamp(distance - dt * 5, 0, maxDist)
end
if push then
distance = math.clamp(distance + dt * 5, 0, maxDist)
end
end
end)
function RecursiveParent(part : BasePart)
local currentParent = part:FindFirstAncestorOfClass("Model")
local nextParent = currentParent
repeat
currentParent = nextParent
nextParent = nextParent:FindFirstAncestorOfClass("Model")
until nextParent == nil
return currentParent
end
function GetMouseHit()
if not rootParent then
return
end
local params = RaycastParams.new()
params.FilterDescendantsInstances = { rootParent, script.Parent }
params.FilterType = Enum.RaycastFilterType.Exclude
params.RespectCanCollide = false
params.IgnoreWater = true
return workspace:Raycast(workspace.CurrentCamera.CFrame.Position, mouse.UnitRay.Direction * maxDist, params)
end