How can I make a road infinite?

I want my car to stay still, but the road to move, then clone it when it reaches the end. Giving it an illusion that the car is moving. This is what I’m using to move the road.

rs.Heartbeat:Connect(function()
    road:SetPrimaryPartCFrame(road.Hitbox.CFrame + Vector3.new(0,0,0.5))
end)
4 Likes

You could constantly increase the size of the road example:

while true do
wait()
road.Size += Vector3.new(0,0,1) --[[ Change to the direction you want to make 
the road bigger --]]
end
-- Or you could move the road
while true do
wait()
road.Position += Vector3.new(0,0,1)
end

But it’s a model, and that would scale it in a weird way. I just want to clone and remove parts while moving the road.

You could use for i,v in pairs and scale every child of the model.

for i,v in pairs(script.Parent:GetChildren()) do
v.Size += Vector3.new(0,0,1)
end

Wouldn’t that be very laggy? The model contains many parts.

I would create at least 3 smaller models so you are not having 2 huge repeating models constantly being CFramed across the map.
Just have each model move along with the previous one, then teleport it ahead of you after you pass by it and it’s out of camera range.
Test it to see if any lag is decreased instead of Destroying and Cloning the map sections each time.
Edited

rs.Heartbeat:Connect(function()
    road:SetPrimaryPartCFrame(road.Hitbox.CFrame + Vector3.new(0,0,0.5))
    if road.PrimaryPart.Position == (whatever your end Position is) then road.PrimaryPart.Position = (whatever your start Position is)
end)

Obviously not a perfect script to deal with all 3 models, but it shows how it can be accomplished.

I know how I want it to work, but I don’t know how to code it.

local roadModel = game.ServerStorage.Road
local roadCFrame = firstRoad:GetPivot() -- cframe of first placed road model

rs.Heartbeat:Connect(function()
    if (localPlayer.Position - roadCFrame.Position).Magnitude > setDistance then
        local newRoad = roadModel:Clone()
        newRoad:PivotTo(roadCFrame * roadSize)
        roadCFrame = newRoad:GetPivot()
        newRoad.Parent = workspace
    end
end)

I reckon something like this will help you further. Of course you need to add a garbage collection after passing every something like 3rd new road generation (you could do this with the module (%) operater).

I see you used localplayer, how can I do it on the server?

Is this a 1 player game, or more than 1?
If it’s a 1 player game there will be better performance if you do it locally.

The game is more than 1 players.

Also, what would roadsize and setdistance be?

It is typically more beneficial to do it for the player, because the server would have to render and calculate this for every player (which could cause some roads being very long because the roads, for example, each have 1 player). I would really recommend not doing it on the server.

If you do want to do it, you’ll probably end up creating lag instead of trying to remove it.
Again, if you do want to do it, just hook it up to players:GetPlayers()

roadsize and setdistance speak for themselves, actually.
roadsize would stand for the size of the road in the direction towards where the road is cloned
setdistance would be how much distance a player would be from the center position of the road before generating a new road

1 Like

This is what I have.

local roadModel = game.ReplicatedStorage.Road
local roadCFrame = workspace.Roads.Road:GetPivot()

game:GetService("RunService").Heartbeat:Connect(function()
	if (game.Players.LocalPlayer.Character.HumanoidRootPart.Position - roadCFrame.Position).Magnitude > 1 then
		local newRoad = roadModel:Clone()
		newRoad:PivotTo(roadCFrame * workspace.Roads.Road.Hitbox.Size)
		roadCFrame = newRoad:GetPivot()
		newRoad.Parent = workspace
	end
end)

I don’t know how to get setdistance, so I just put it at 1.
I get an error Unable to cast Vector3 to CoordinateFrame.

I more kind of made it to be pseudocode, to show you the way you should go to. I don’t think it is actually in a working state how you’ve written it now.

Regardless, the error pertains because you are getting Size in

roadCFrame * workspace.Roads.Road.Hitbox.Size

Because Size returns a Vector3 and you multiply it with a CFrame

1 Like

This is what I get.
image

roadsize would stand for the size of the road in the direction towards where the road is cloned
Not all directions. (depending on the rotation use X or Z or Y, not all)

Now it clones infinitely, but doesn’t move or delete. How could I fix that?

By properly checking the distance.

Now I have this, it clones and move, but how can I delete those that I’ve already passed?

local roadModel = game.ReplicatedStorage.Road
local roadCFrame = workspace.Roads.Road:GetPivot()

game.Players.LocalPlayer.CharacterAdded:Wait()

function clone()
	if (game.Players.LocalPlayer.Character.HumanoidRootPart.Position - roadCFrame.Position).Magnitude > 1 then
		local newRoad = roadModel:Clone()
		newRoad:PivotTo(roadCFrame * CFrame.new(0,0,-workspace.Roads.Road.Hitbox.CFrame.Z))
		roadCFrame = newRoad:GetPivot()
		newRoad.Parent = workspace.Roads
	end
end

game.ReplicatedStorage.MoveRoad.OnClientEvent:Connect(function()
	game:GetService("RunService").Heartbeat:Connect(function()
		for _,v in pairs(workspace.Roads:GetChildren()) do
			v:SetPrimaryPartCFrame(v.Hitbox.CFrame + Vector3.new(0,0,1))
		end
		clone()
	end)
end)