You could probably do some kinda system like this:
--settings
local base_mod = 0.1 --this is how much the heads will curl based on movement
local sine_mod = 0.2 --this is how much the heads will "bounce" as it moves
local sine_speed = 10 --this is how often the heads will "bounce" as it moves
local lerp_mod = 0.2 --this is how fast the heads will reach their goal position, like time on a tween
while true do
for i, head in next, neckSegments do
local weld = head.Weld
local angle = -humanoid.MoveDirection.Magnitude * (base_mod + sine_mod * math.abs(math.sin(tick() * sine_speed)) )
weld.C0 = weld.C0:Lerp(CFrame.Angles(angle, 0, 0), lerp_mod)
end
wait() --you can replace this with runservice.Heartbeat:Wait() or smthn if you want
end
(This system is assuming youre using C1 to offset the heads, if you use C0 you might have to remove the negative on the “local angle = -humanoid.Mo…” line and switch the next line from “weld.C0” to “weld.C1”)
I am using C0 and C1 to position the segments. When I did what You sent me, all the segments go into each other without gaps and sometimes they go into the torso. When I’m walking segment1 rotates in other direction than segmnet2. I will show you my script, maybe You can fix something or maybe You will show me how to make it easier. Sorry for confusing but I’m Lua beginner so I don’t know a lot of things.
There is also script that set transparency of head to 0 and creates fake head because I can’t move character head.
local Weld1 = Instance.new("Weld") --Creates first neck segment to make it easier.
Weld1.Name = "WeldX"
Weld1.Parent = script.NeckSegment
Weld1.Part1 = Torso
Weld1.Part0 = script.NeckSegment
Weld1.C1 = TorsoAttachment.CFrame --TorsoAttachment is attachment at top of UpperTorso.
Weld1.C0 = script.NeckSegment.Down.CFrame -- "Down" Attachment is attachment at bottom of neck segment. And "Up" is attachment at top of neck segment.
local FirstNeckSegment = script.NeckSegment:Clone()
FirstNeckSegment.Name = "Segment1"
FirstNeckSegment.Parent = Segments
FirstNeckSegment.CanCollide = true
FirstNeckSegment.Massless = true
FirstNeckSegment.Color = Head.Color
function CreateSegment() -- "Segments" is folder that contains all segments. S is number of segments.
S = S + 1
local OldNeckSegment = Segments:FindFirstChild("Segment"..S-1)
local NewNeckSegment = script.NeckSegment:Clone()
NewNeckSegment.Parent = Segments
NewNeckSegment.Name = "Segment"..S
NewNeckSegment.Color = Head.Color
NewNeckSegment.CanCollide = true
NewNeckSegment.Massless = true
NewNeckSegment.CFrame = OldNeckSegment.CFrame + Vector3.new(0,OldNeckSegment.Size.Y,0)
NewWeld = Instance.new("Weld") -- Creates weld and sets its position above the previous one.
NewWeld.Parent = NewNeckSegment
NewWeld.Name = "WeldX"
NewWeld.Part1 = OldNeckSegment
NewWeld.Part0 = NewNeckSegment
NewWeld.C1 = OldNeckSegment.Up.CFrame
NewWeld.C0 = NewNeckSegment.Down.CFrame
end
NeckCount.Changed:Connect(function() -- When "NeckCount" value changes it destroys all segments and make new.
S = 1
for i, v in pairs(Segments:GetChildren()) do
if v.Name ~= "Segment1" then
v:Destroy()
end
end
for i = 1, NeckCount.Value, 1 do
wait(0.1)
CreateSegment()
end
end)
NeckCount.Value = 0
NeckCount.Value = 1
--settings
local base_mod = 0.1 --this is how much the heads will curl based on movement
local sine_mod = 0.2 --this is how much the heads will "bounce" as it moves
local sine_speed = 10 --this is how often the heads will "bounce" as it moves
local lerp_mod = 0.2 --this is how fast the heads will reach their goal position, like time on a tween
while true do
for i, head in next, Segments:GetDescendants() do
if head.Name == "WeldX" then
local weld = head
local angle = -Humanoid.MoveDirection.Magnitude * (base_mod + sine_mod * math.abs(math.sin(tick() * sine_speed)) )
weld.C0 = weld.C0:Lerp(CFrame.Angles(angle, 0, 0), lerp_mod)
end
end
wait() --you can replace this with runservice.Heartbeat:Wait() or smthn if you want
end
I would personally do the create segment script a bit more like this:
function CreateSegment() -- "Segments" is folder that contains all segments. S is number of segments.
S = S + 1
local OldNeckSegment = Segments:FindFirstChild("Segment"..S-1)
local NewNeckSegment = script.NeckSegment:Clone()
NewNeckSegment.Name = "Segment"..S
NewNeckSegment.Color = Head.Color
NewNeckSegment.CanCollide = true
NewNeckSegment.Massless = true
NewWeld = Instance.new("Weld") -- Creates weld and sets its position above the previous one.
NewWeld.Name = "WeldX"
NewWeld.Part1 = OldNeckSegment
NewWeld.Part0 = NewNeckSegment
NewWeld.C1 = CFrame.new(0,1,0)
NewWeld.Parent = NewNeckSegment --performance benefit of parenting after setting properties
NewNeckSegment.Parent = Segments
end
That should work with the exact script I have in the post above (hopefully)
Okay, Thank You for help. It works now. My last question is how to decrease the segments curl? If there is a lot of segments (for example 25 or more) it curls too much. I tried to divide the base_mod and sine_mod by segment count but it stopped to curl.
Sorry for replying again, but I saw that lerping is very laggy.
When the number of segments exceeds 100, the script’s activity is already ~3% and it starts to lag. When I deleted 2 lines of script:
The script activity was same, but it stopped lagging with larger numbers of segments. Is there any way to reduce the lags? I tried to stop the loop when player is not moving, but it started to lag again when I started to walk. I also tried while true do loop and heartbeat loop but it was lagging too.