Quick and short,
- This is made with nodes and beams
- The grapple will straighten out once it reaches it end location
Video :
Place : Grapple Effect - Roblox
Code :
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local Player = Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local RootPart = Character:WaitForChild("HumanoidRootPart")
local Camera = workspace.CurrentCamera
local GrappleSpeed = 800
local NodeCount = 20
local BeamThickness = 0.8
local WaveCount = 3
local WaveHeight = 1
local SpringDamper = 5
local SpringVelocity = 10
local StraightenSpeed = 10
local Nodes = table.create(NodeCount)
local Beams = table.create(NodeCount - 1)
local GrapplePoint = nil
local IsGrappling = false
local SpringValue = 0
local GrappleProgress = 0
local IsStraightening = false
local function CreateNode(position)
local Node = Instance.new("Part")
Node.Anchored = true
Node.CanCollide = false
Node.Size = Vector3.new(0.1, 0.1, 0.1)
Node.Transparency = 0.5
Node.Color = Color3.new(0, 0, 0)
Node.Position = position
Node.Parent = workspace
return Node
end
local function CreateBeam(StartNode, EndNode)
local Beam = Instance.new("Beam")
Beam.Attachment0 = Instance.new("Attachment", StartNode)
Beam.Attachment1 = Instance.new("Attachment", EndNode)
Beam.Width0 = BeamThickness
Beam.Width1 = BeamThickness
Beam.Color = ColorSequence.new(Color3.new(0, 0, 0))
Beam.Parent = workspace
Beam.FaceCamera = true
return Beam
end
local function CleanupGrapple()
for _, Node in ipairs(Nodes) do
Node:Destroy()
end
for _, Beam in ipairs(Beams) do
Beam:Destroy()
end
table.clear(Nodes)
table.clear(Beams)
end
local function CreateGrapple()
CleanupGrapple()
for i = 1, NodeCount do
Nodes[i] = CreateNode(RootPart.Position)
if i > 1 then
Beams[i - 1] = CreateBeam(Nodes[i - 1], Nodes[i])
end
end
end
local function UpdateSpring(DeltaTime)
if IsStraightening then
SpringValue = 0
else
local Delta = SpringVelocity * DeltaTime
SpringValue = SpringValue + Delta
SpringValue = SpringValue * (1 - SpringDamper * DeltaTime)
end
end
local function UpdateGrapple(DeltaTime)
if not GrapplePoint or not RootPart then return end
local Direction = (GrapplePoint - RootPart.Position).Unit
local Distance = (GrapplePoint - RootPart.Position).Magnitude
GrappleProgress = math.min(GrappleProgress + GrappleSpeed * DeltaTime, Distance)
local T = GrappleProgress / Distance
if IsStraightening then
for i = 1, NodeCount do
local NodeT = i / NodeCount
local TargetPosition = RootPart.Position + Direction * (NodeT * Distance)
Nodes[i].Position = Nodes[i].Position:Lerp(TargetPosition, DeltaTime * StraightenSpeed)
end
else
for i = 1, NodeCount do
local NodeT = i / NodeCount
local CurveOffset = CFrame.lookAt(RootPart.Position, GrapplePoint).UpVector * WaveHeight * math.sin(NodeT * WaveCount * math.pi) * SpringValue
local NodePosition = RootPart.Position + Direction * (NodeT * GrappleProgress) + CurveOffset
Nodes[i].Position = Nodes[i].Position:Lerp(NodePosition, DeltaTime * 10)
end
if GrappleProgress >= Distance then
IsStraightening = true
SpringValue = 0
end
end
end
UserInputService.InputBegan:Connect(function(Input, GameProcessed)
if GameProcessed then return end
if Input.UserInputType == Enum.UserInputType.MouseButton1 then
local MouseRay = Camera:ScreenPointToRay(Input.Position.X, Input.Position.Y)
local RaycastParams = RaycastParams.new()
RaycastParams.FilterType = Enum.RaycastFilterType.Blacklist
RaycastParams.FilterDescendantsInstances = {Character}
local Result = workspace:Raycast(MouseRay.Origin, MouseRay.Direction * 1000, RaycastParams)
if Result then
GrapplePoint = Result.Position
IsGrappling = true
IsStraightening = false
GrappleProgress = 0
SpringValue = 1
CreateGrapple()
end
end
end)
UserInputService.InputEnded:Connect(function(Input, GameProcessed)
if Input.UserInputType == Enum.UserInputType.MouseButton1 then
IsGrappling = false
IsStraightening = false
CleanupGrapple()
end
end)
RunService.RenderStepped:Connect(function(DeltaTime)
if IsGrappling then
UpdateSpring(DeltaTime)
UpdateGrapple(DeltaTime)
end
end)