Shape-only spring constraints

I’m currently making a grapple hook. This grapple was made with rope constraints and the shape was a bit plain, so I used spring constraints to create a pretty decent grapple hook. However, when I fired the hook using FastCast, I ran into an issue where the player would freeze while the hook was stuck in the ground. I would like the spring to just have its shape, or for the player to move while it’s being fired.

local module = require(game.ReplicatedStorage.FastCastRedux)

game.ReplicatedStorage.HookFireEvent.OnServerEvent:Connect(function(plr, position, value)
	local caster = module.new()

	local params = RaycastParams.new()
	params.FilterType = Enum.RaycastFilterType.Blacklist
	params.IgnoreWater = true

	local cb = module.newBehavior()
	cb.RaycastParams = params
	cb.Acceleration = Vector3.new(0, -workspace.Gravity/1.5, 0)
	cb.AutoIgnoreContainer = false
	cb.MaxDistance = 200000
	cb.CosmeticBulletContainer = workspace.Bullets
	cb.CosmeticBulletTemplate = game.ReplicatedStorage.hook

	module.VisualizeCasts = false

	caster.LengthChanged:Connect(function(cast, lastpoint, direction, length, velocity, bullet)
		if bullet then
			local bul = bullet.Size.Z/2
			local offset = CFrame.new(0, 0, -(length - bul))
			bullet.CFrame = CFrame.lookAt(lastpoint, lastpoint + direction):ToWorldSpace(offset) * CFrame.Angles(0, math.rad(180), 0)
		end
	end)
	
	params.FilterDescendantsInstances = {plr.Character}
	cb.RaycastParams = params

	local origin = plr.Character.Handle.Handle.Position
	local direction = ((position + Vector3.new(0, 0.5, 0)) - origin).Unit

	caster:Fire(origin, direction, 400, cb, plr)
	
	local rope1 = Instance.new("RopeConstraint")
	local visual = game.ReplicatedStorage.VisualSpring:Clone()
	visual.Parent = game.ReplicatedStorage
	visual.Coils = 8
	visual.Radius = 1.5

	local tween = game.TweenService:Create(
		visual, 
		TweenInfo.new(1.25, Enum.EasingStyle.Exponential, Enum.EasingDirection.Out), 
		{Coils = 0, Radius = 0.15}
	)

	local brick = Instance.new("Part") --Creates the part where the Attachment will be held
	brick.Size = Vector3.new(0.05,0.05,0.05)
	brick.Parent = game.Workspace
	brick.Transparency = 1
	brick.CanCollide = false
	brick.Anchored = true
	brick.Position = position --Brick positioned on click
	brick.Name = plr.Name.."attb"
	local UA = Instance.new("Part")
	UA.Size = Vector3.new(0.5,0.5,0.5) --Creates the Unanchored part that is attached to the other brick
	UA.CustomPhysicalProperties = PhysicalProperties.new(100,0,0,0,0) --Make it the heaviest it can be to stop it from bugging out
	UA.Parent = brick
	UA.Shape = "Ball"
	UA.Transparency = 1
	UA.CanCollide = false
	UA.Anchored = false
	UA.Position = brick.Position --Put it inside the brick
	local UAatt = Instance.new("Attachment") --Attachment the goes inside the ball
	UAatt.Parent = UA
	UAatt.WorldPosition = UA.Position
	local Brickatt = Instance.new("Attachment") --Attachment that goes inside the brick
	Brickatt.Parent = brick
	Brickatt.WorldPosition = brick.Position
	caster.LengthChanged:Connect(function(cast, lastpoint, direction, length, velocity, bullet)
		if bullet then
			brick.Position = bullet.Position
			UA.Position = brick.Position
			UAatt.WorldPosition = UA.Position
			Brickatt.WorldPosition = brick.Position
		end
	end)
	local BrUARope = Instance.new("RopeConstraint") --Creates a rope between the anchored brick and the unachored ball it in place
	BrUARope.Parent = brick
	BrUARope.Attachment0 = Brickatt
	BrUARope.Attachment1 = UAatt
	BrUARope.Length = 0.1
	BrUARope.Thickness = 1
	rope1.Thickness = 0
	rope1.Color = BrickColor.new(0, 0, 0)
	visual.Parent = plr.Character
	visual.Attachment0 = plr.Character.HumanoidRootPart.RootAttachment
	visual.Attachment1 = UAatt
	visual.Coils = 4
	visual.Radius = 1.5
	tween:Play()
	
	caster.RayHit:Connect(function(cast, result, velocity, bullet)
		if bullet and result then
			rope1.Attachment0 = plr.Character.Torso.BodyFrontAttachment
			rope1.Attachment1 = UAatt
			rope1.Parent = plr.Character
			rope1.Name = "Rope"
			rope1.Length = plr:DistanceFromCharacter(brick.Position) + 2
			rope1.Visible = true
			local hit = result.Instance
			local char = hit.Parent
			local hum = char:FindFirstChildWhichIsA("Humanoid")
			if hum then
				hum:TakeDamage(10)
			end
			bullet.CFrame *= CFrame.new(0, 0, .5)
			bullet.Anchored = true
		end
	end)
end)

game.ReplicatedStorage.HookPullEvent.OnServerEvent:Connect(function(plr)
	local rope1:RopeConstraint = plr.Character:FindFirstChild("Rope")
	local visual:SpringConstraint = plr.Character:FindFirstChild("VisualSpring")
	
	local accle = 0
	local value = true
	
	if rope1 and visual then
		while value == true do
			task.wait()
			accle += 0.25
			rope1.Length -= accle
			if rope1.Length <= 1 then
				rope1:Destroy()
				visual:Destroy()
				local ropedelete = game.Workspace:FindFirstChild(plr.Name.."attb") --Deletes everything
				ropedelete:Destroy()
				game.ReplicatedStorage.HookEvent:FireClient(plr)
				if workspace.Bullets:FindFirstChild(plr.Name.."sBullet") then
					workspace.Bullets:FindFirstChild(plr.Name.."sBullet"):Destroy()
				end
				value = false
			else
				
			end
		end
	end
end)

Main Script

repeat wait() until game.Players.LocalPlayer
local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
local accle = 0
local rope1 = Instance.new("RopeConstraint")
local visual = game.ReplicatedStorage.VisualSpring:Clone()
visual.Parent = game.ReplicatedStorage
visual.Coils = 4
visual.Radius = 1
local tween = game.TweenService:Create(
	visual, 
	TweenInfo.new(0.25, Enum.EasingStyle.Exponential, Enum.EasingDirection.Out), 
	{Coils = 0, Radius = 0.15}
)

local function onMouseClick(position)
	if script.Value.Value == false then
		script.Value.Value = true
		game.ReplicatedStorage.HookFireEvent:FireServer(mouse.Hit.Position, script.Value.Value)
	end
end

local function onMouseUp()
	local pull = player.Character:WaitForChild("Humanoid").Animator:LoadAnimation(player.Character.Pull)
	local pull2 = player.Character:WaitForChild("Humanoid").Animator:LoadAnimation(player.Character.Pull2)
	
	pull:Play()
	task.delay(pull.Length, function()
		if script.Value.Value then
			pull2:Play()
		end
	end)
	while script.Value.Value do
		task.wait()
		accle += 0.25
		rope1.Length -= accle
		if rope1.Length <= 1 then
			accle = 0
			rope1.Parent = game.ReplicatedStorage
			visual.Parent = game.ReplicatedStorage
			local ropedelete = game.Workspace:FindFirstChild(player.Name.."attb") --Deletes everything
			ropedelete:Destroy()
			script.Value.Value = false
			script.Parent.Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
		else
			script.Parent.Humanoid:ChangeState(Enum.HumanoidStateType.Physics)
		end
	end
	pull2:Stop()
end

game.ReplicatedStorage.HookEvent.OnClientEvent:Connect(function()
	script.Value.Value = false
	script.Parent.Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
end)

mouse.Button1Down:Connect(function()
	onMouseClick()
end)

mouse.Button1Up:Connect(function()
	game.ReplicatedStorage.HookPullEvent:FireServer()
	script.Parent.Humanoid:ChangeState(Enum.HumanoidStateType.Physics)
end)

Local script

image
Character

By “the spring to just have its shape” do you mean you want to add a spring without affecting the physics at all?

A good first thing to try might be setting the MaxForce to 0 and LimitsEnabled to false.

If nothing simple like that works, you could just have the spring be between two totally separate parts/attachments and continuously re-position the parts to the points you want the spring between.