AlignPosition causing weird setback when instantiated on objects

  1. What do you want to achieve? Keep it simple and clear!
    I want to fix the really irritating jitter caused when grabbing stuff

  2. 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

  3. 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

Found the fix and it was quite obvious so the slip-up is embarrassing; I’m creating the AlignPosition but not assigning the position of it until the next frame so the physics step has time to move the part to the default position (0, 0, 0)

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.