How are curved cart ride tracks made so smoothly?

i am currently making a cart ride game with suspension, i want to make a track that includes a turn but its diagonal but i just cant get it right, ive tried archimedies, and gap fill but it makes it look really janky and not what i want, in the image below shows the idea of how i want my tracks to be like, is there a plugin i should know about?

another question is how do they turn the curved track back to a straight track without it breaking?

4 Likes

Since i am a professional builder, i would probably use a plugin called “Archimedes”, it lets you easily create circles/curves

That plugin cannot create a curve like this

1 Like

Any follow ups on this? Im also intrested in what game that screenshot came from

Not quite sure on this one, but maybe It could’ve been executed by using Bezier Curves?
I think It could be it.

1 Like

cart ride delivery service im pretty sure

2 Likes

Hello, i am someone else suffering attempting to find a plugin for this, if someone could make a plugin that makes bezier curves (WITH TILT AND ROLL) and allows us to use our own custom “rail” models, it would help a bunch. :grinning_face:

i had this same issue and i ended up making my own solution. i have something that works thats (almost) literally this but the ONE thing thats preventing me from finishing it is connecting the actual track pieces together. i honeslty have no idea how ill do that, as im making this for both a cart ride game and a theme park sandbox game. if ur smart at math n stuff pls lmk

1 Like

Can you share the plugin for this?

local startvalueLEFT = game.ReplicatedStorage.Values.StartPieceLEFT
local endvalueLEFT = game.ReplicatedStorage.Values.EndPieceLEFT
local startvalueRIGHT = game.ReplicatedStorage.Values.StartPieceRIGHT
local endvalueRIGHT = game.ReplicatedStorage.Values.EndPieceRIGHT

local middistance = 5

local middleTemplate = game.ReplicatedStorage.Pieces.Concrete
local middleBetweenSidesTemplate = game.ReplicatedStorage.Pieces.Middle

local middlePiecesFolder = workspace:FindFirstChild("MiddlePieces")
if not middlePiecesFolder then
	middlePiecesFolder = Instance.new("Folder")
	middlePiecesFolder.Name = "MiddlePieces"
	middlePiecesFolder.Parent = workspace
end

local function createFiller(fromPart, toPart)
	local filler = middleTemplate:Clone()
	local center = (fromPart.Position + toPart.Position) / 2
	local distance = (fromPart.Position - toPart.Position).Magnitude
	filler.Size = Vector3.new(fromPart.Size.X, fromPart.Size.Y, distance - 1)
	filler.CFrame = CFrame.new(center, toPart.Position) * CFrame.Angles(0, math.pi, 0)
	filler.Anchored = true
	filler.Parent = game.Workspace.MergedConnectors
end

local function createMiddleBetween(leftPart, rightPart)
	local middlePart = middleBetweenSidesTemplate:Clone()
	local centerpos = (leftPart.Position + rightPart.Position) / 2
	local centerori = (leftPart.Orientation + rightPart.Orientation) / 2
	middlePart.Position = centerpos
	middlePart.Orientation = centerori
	middlePart.Anchored = true
	middlePart.Parent = middlePiecesFolder
end


local function processSidePieces(startValue, endValue, sideName)
	local pieces = {}
	local part = script.Parent.Parent:FindFirstChild(sideName)
	startValue.Value = part

	while part do
		table.insert(pieces, part)

		local sphere = Instance.new('Part')
		sphere.Anchored = true
		sphere.Transparency = 0.5
		sphere.Size = Vector3.new(0.25, 0.25, 0.25)
		sphere.Name = sideName .. '_touchSphere'

		local offsetDistance = part.Size.Z / 2
		sphere.CFrame = part.CFrame * CFrame.new(0, 0, offsetDistance)
		sphere.Parent = workspace

		local touchingParts = sphere:GetTouchingParts()
		sphere:Destroy()

		if #touchingParts > 0 then
			local nextPart = nil
			for _, p in ipairs(touchingParts) do
				if p ~= part then
					nextPart = p
					break
				end
			end

			if nextPart then
				part = nextPart
			else
				break
			end
		else
			break
		end
	end

	endValue.Value = pieces[#pieces]
	return pieces
end

local leftPieces = processSidePieces(startvalueLEFT, endvalueLEFT, "Left")
local rightPieces = processSidePieces(startvalueRIGHT, endvalueRIGHT, "Right")

local function placeFillersAndCleanup(pieces)
	local inStraightRun = false
	local currentRunStart = nil
	local lastStraightPiece = nil
	local straightParts = {}

	for i = 1, #pieces do
		local part = pieces[i]
		local nextPart = pieces[i + 1]

		if nextPart and (nextPart.Orientation - part.Orientation).Magnitude < 0.01 then
			if not inStraightRun then
				inStraightRun = true
				currentRunStart = part
				straightParts = { part }
			end
			table.insert(straightParts, nextPart)
			lastStraightPiece = nextPart
		else
			if inStraightRun and currentRunStart and lastStraightPiece and currentRunStart ~= lastStraightPiece then
				createFiller(currentRunStart, lastStraightPiece)
				for j = 2, #straightParts - 1 do
					if straightParts[j] and straightParts[j].Parent then
						straightParts[j]:Destroy()
					end
				end
			end
			inStraightRun = false
			currentRunStart = nil
			lastStraightPiece = nil
			straightParts = {}
		end
	end
end

placeFillersAndCleanup(leftPieces)
placeFillersAndCleanup(rightPieces)

local minCount = math.min(#leftPieces, #rightPieces)

for i = middistance, minCount, middistance do
	createMiddleBetween(leftPieces[i], rightPieces[i])
end

its not a plugin its my own script but this is the code for it but youll have to adjust it to add ur own models to each bezier point. youll need bhristt’s bezier curve module. also this is an old version tho, i can’t sent the new one cause i changed how it works more so to fit the needs for making rollercoaster tracks than cart ride tracks. ill sent that one too if you’d really like but i cant guarantee it can work to make cart ride tracks

1 Like

you can adapt stravant’s resizealign to work with your plugin pretty easily, make a module out of it

i did end try that but gapfill did not smoothly connect them so i ended up just modyifying the script so that it made a part that touches the 2 points in between them on the left and ride side but i realized how useful it could be for my theme park thing so ive more so adapted it for that instead

https://streamable.com/qsbpqv

The video shows it working, but using parts to bridge the gap is still just a linear fix. If you’re already using a Bezier module, you should be calculating the CFrame at the curve segments directly instead of trying to patch gaps between straight pieces.