I want a trail that has infinite lifetime. Is there any way?
Since Trails are limited to 20 seconds what if you just ‘paint’ the line with a line of Parts? It may not be as clean a a Trail, but it would be permanent.
I’ve already tested that and it looks quite bad
Is there any other way to do this without the part cloning method?
I’m not a scripter by any means, but you could try moving invisible parts with a trail along the path created at intervals to “remake” the trail, or move a part along the path just as the trail is dissapearing.
That would work!
I made a small proof of concept of that here.
I’m still pretty new to scripting, but I thought this would be fun for me to try.
Here’s what I did in plain English.
1,
Repeatedly run a check to see if your targets position has changed more than X amount of studs from your last accepted position log
If it has, Log the position in a table
If it hasnt, just keep on looping until it does.
It is important to ensure that your target has actually moved instead of just spamming the table with positions every Y amount of seconds. You can check the position between 2 Vector3 values via a .Magnitude check. You should have a small increment between each value you log in your table.
2,
Independently form the prior loop,
Run a pairs loop on your position table moving a part with a trail in it along all of the recorded positions with a short task.wait() in-between each position change.
You can run sections of code independently via task.spawn()
Heres a video of it in practice
I used a hyper link, because it wont embed and I can’t upload it.
This code should just be used as a reference.
Change okayendo in “target” to your username, then run the script in your studio command bar while playtesting.
local PositionTable = {}
local target = game.Players["okayendo"].Character.HumanoidRootPart
local function LogPosition()
table.insert(PositionTable,target.Position)
print("Logged position! There are a total of "..#PositionTable.." positions logged!")
end
--
local LastPosition = nil
local function CheckMovement()
print("check called!")
if not LastPosition then
LastPosition = target.Position
else
local magcheck = (LastPosition - target.Position).Magnitude
if magcheck > 3 then
LastPosition = target.Position
print("The player has moved enough!")
LogPosition()
else
print("The player has not moved enough!")
end
end
end
--
--visualize the trail
--This should just be a part thats cloned from replicated storage, but for the example I just made it in this script.
local trailpart = Instance.new("Part")
trailpart.Anchored = true
trailpart.Size = Vector3.new(0.1,0.1,0.1)
trailpart.Transparency = 0
trailpart.CanCollide = false
local trail = Instance.new("Trail")
trail.FaceCamera = true
trail.Lifetime = 20
trail.Parent = trailpart
local attach0 = Instance.new("Attachment")
local attach1 = Instance.new("Attachment")
attach0.Parent = trailpart
attach1.Parent = trailpart
attach0.Position = Vector3.new(0,1,0)
attach1.Position = Vector3.new(0,-1,0)
trail.Attachment0 = attach0
trail.Attachment1 = attach1
--
local Debris = game:GetService("Debris")
task.spawn(function() -- runs independantly
while true do
task.wait(1)
task.spawn(function() -- runs independantly
print("Visualizing!")
local newtrail = trailpart:Clone()
newtrail.Parent = workspace
for i,e in pairs(PositionTable) do
newtrail.Position = e
task.wait()
end
Debris:AddItem(newtrail,5)
end)
end
end)
task.spawn(function() -- runs independantly
while true do
task.wait(0.3)
CheckMovement()
end
end)
--```
After a certain amount of movement, place an invisible marker and connect it to the previous marker with a beam. It should look the same as the trail but will last forever and you can edit it after the fact.
You did a tremendous work over there. Thanks for such time dedicated to solve this problem. By the moment I’m looking for the best way to make the infinite trail, if there is no other solution, I’ll mark your answer as solution…
How do I do that? Can you send a video about it?
Put this together really quickly, tested minimally
local Players = game:GetService("Players")
local Player = Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
Player.CharacterAdded:Connect(function(C)
Character = C
end)
local REFRESH_RATE = 0 -- how often does it check the characters position
local RESOLUTION_DISTANCE = 1 -- how far does the character need to be from its last position to make a new point
local Markers = {}
while true do
if Character then
local Position = Character:GetPivot().Position
if #Markers == 0 or (Position - Markers[#Markers].Position).Magnitude >= RESOLUTION_DISTANCE then
local Marker = Instance.new("Part")
Marker.CanCollide = false
Marker.CanQuery = false
Marker.CanTouch = false
Marker.Transparency = 1
Marker.Anchored = true
Marker.Position = Position
Marker.Parent = workspace
local Attachment = Instance.new("Attachment")
Attachment.Parent = Marker
if #Markers ~= 0 then
local Beam = Instance.new("Beam")
Beam.Attachment0 = Attachment
Beam.Attachment1 = Markers[#Markers]:FindFirstChildOfClass("Attachment")
Beam.Parent = Markers[#Markers]
Beam.FaceCamera = true
end
table.insert(Markers,Marker)
end
end
task.wait(REFRESH_RATE)
end
I would edit the refresh rate and resolution, put them super low for testing, but in an actual game it would make too many parts
Basically rewrote it cause my first one sucked and it was an interesting problem
local Players = game:GetService("Players")
local Runservice = game:GetService("RunService")
local Player = Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
Player.CharacterAdded:Connect(function(C)
Character = C
end)
local REFRESH_RATE = 0 -- how often does it check the character's position
local RESOLUTION_DISTANCE = 1 -- how far does the character need to be from its last position to make a new point
local Markers = {}
local LastAngle = 0
function DegreeBetweenVectors(a, b)
return math.deg(math.acos(math.clamp(a.Unit:Dot(b.Unit),-1,1)))
end
local function MakeMarker(Position)
local Marker = Instance.new("Part")
Marker.CanCollide = false
Marker.CanQuery = false
Marker.CanTouch = false
Marker.Size = Vector3.new(0.1,0.1,0.1)
Marker.Color = Color3.fromRGB(255, 0, 0)
--Marker.Transparency = 1
Marker.Anchored = true
Marker.Position = Position
Marker.Parent = workspace
local Attachment = Instance.new("Attachment")
Attachment.Parent = Marker
LastAngle = 0
if #Markers ~= 0 then
local Beam = Instance.new("Beam")
Beam.Attachment0 = Attachment
Beam.Attachment1 = Markers[#Markers]:FindFirstChildOfClass("Attachment")
Beam.Parent = Marker
Beam.FaceCamera = true
end
table.insert(Markers,Marker)
end
local PreviousTime = os.time()
Runservice.Heartbeat:Connect(function()
if PreviousTime + REFRESH_RATE < os.time() then
if Character then
local ConsideredPosition = Character:GetPivot().Position
if #Markers == 0 or (ConsideredPosition - Markers[#Markers].Position).Magnitude >= RESOLUTION_DISTANCE then
local PreviousMarker = Markers[#Markers]
if #Markers >= 2 then
local DegreesBetween = DegreeBetweenVectors(ConsideredPosition - PreviousMarker.Position,PreviousMarker.Position-Markers[#Markers-1].Position)
local Marker = Markers[#Markers]
print(LastAngle)
if DegreesBetween < 3 and LastAngle < 3 then
LastAngle += DegreesBetween
Marker.Position = ConsideredPosition
return
end
end
MakeMarker(ConsideredPosition)
end
end
end
end)
That works perfectly, thanks this I what I wanted
This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.