[]HELP!] - How do I make an endless trail?

I want a trail that has infinite lifetime. Is there any way?

1 Like

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.

1 Like

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.

1 Like

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)

--```
2 Likes

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.

1 Like

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…

1 Like

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.