How can I make my CFrame Coaster smoother?

Hello!
I need help with this as I’ve been stuck for a while.

https://gyazo.com/d75ea7e1a32bb6bc51bb0da24671a422

As you can see from the video, the ride only changes speed when it touches a blue dot.

Is there any way to make this smoother? Maybe add some kind of gravity to it?
Thank you!

You can try having specific dots to change the speed, and not every blue dot. For example, you can change the speed of the coaster from dot1 to dot5 instead of dot1, dot2, dot3, dot4, and dot5. You would also use a Sine easing style to increase speed for realism.

local speedDots = {dot1 = 1, dot5 = 5} -- {dotNumber = speed}
local trainSpeed = 0.5

local function easeInSine(x) -- For speeding up or slowing down
  return 1 - math.cos((x * math.pi) / 2)
end

local function easeOutSine(x) -- For braking
  return math.sin((x * math.pi) / 2);
end

dot1.Touched:Connect(function()
    local x = -- The percent traveled by the train from dot1 to dot 5 (from 0% - 100%, or 0 - 1)
    local currentdot = speedDots.dot1 -- The current dot
    local nextDot = speedDots.dot5 -- The next dot
    trainSpeed = currentDot + easeInSine(x) * (nextDot - currentDot) -- Speeding up the train
end

Yes and no.

If the next position is higher, then theoretically, the carts should move slower.

If the next position is lower, then it’s vice-versa; move faster.

As for a flat plane, you still have to bear in mind the laws of acceleration, which state that friction will cause you to slow down.

It’s basically a case where you need to bear in mind acceleration, gravity, and other underlying factors. Putting them into play, and making movement non-linear, will help smooth-out your coaster.

1 Like

The only issue with that would be the distancing from each cart. Each cart follows one node behind the cart infront. so if it was one long stretch, it wouldn’t work too well.

Here’s what I have set up for this:

if LASTNODE.Position.Y > node.Position.Y then
		-- GOING DOWN
		if SPEED <= 0.1 then
			SPEED = 0.1
		else
			SPEED -= 0.025
		end
	elseif LASTNODE.Position.Y < node.Position.Y then
		-- GOING UP
		if SPEED >= 0.5 then
			SPEED = 0.5
		else
			SPEED += 0.0125
		end
	elseif LASTNODE.Position.Y == node.Position.Y then
		-- EVEN
	end

It makes it a little bit better, but it accelerates too fast when its going downhill. I wanted to try dividing instead of subtracting. Lemme know what you think.

I’ve edited my previous post for a more in-depth explanation.


To solve that, you can either make the speed of each cart the same as the speed of the cart in front, or make the speed the average speed of the first and last cart.

To solve that, you can either make the speed of each cart the same as the speed of the cart in front

This is actually what I currently do.

I’ve edited my previous post for a more in-depth explanation.

Can you explain it to me more in-depth? I’d love to learn how it works.

Taking the code from my first post:

local speedDots = {dot1 = 1, dot5 = 5} -- {dotNumber = speed}
local trainSpeed = 0.5

local function easeInSine(x) -- For speeding up or slowing down
  return 1 - math.cos((x * math.pi) / 2)
end

local function easeOutSine(x) -- For braking
  return math.sin((x * math.pi) / 2);
end

dot1.Touched:Connect(function()
    local x = -- The percent traveled by the train from dot1 to dot 5 (from 0% - 100%, or 0 - 1)
    local currentdot = speedDots.dot1 -- The current dot
    local nextDot = speedDots.dot5 -- The next dot
    trainSpeed = currentDot + easeInSine(x) * (nextDot - currentDot) -- Speeding up the train
end

What this code is doing is to make it so that It slowly increases speed from one point to another instead of every single point which can cause jankiness. Instead of defining the speed, try defining the change in y level, then calculate the speed based off the distance.

How can I add this onto my code? Here’s what I have currently:

--// SERVICES \\--
local TS = game:GetService("TweenService")

--// MODULES \\--
local EasyTween = require(game.ReplicatedStorage:WaitForChild("EasyClientTween"))
local tweenHandler = EasyTween.new()

--// VARIABLES \\--
local CARTS = script.Parent.Carts
local NODES = script.Parent.Nodes

local START_NODE = 5
local CURRENT_NODE = START_NODE
local SPEED = 0.2

--// OTHER STUFF \\--
local NEW_SPEED = false
local LASTNODE = NODES.Node0

local function tweenRide(ride,node)

local Goal = {["CFrame"] = node.CFrame}
local TI = TweenInfo.new(
	SPEED,
	Enum.EasingStyle.Linear,
	Enum.EasingDirection.InOut,
	0,
	false,
	0
)
local RideTween = TS:Create(ride,TI,Goal)
RideTween:Play()
end


local function setupRide(ride,node)
if NEW_SPEED == false then
	--if node and node:FindFirstChild("Speed") then
	--	SPEED = node.Speed.Value
	--end
	if LASTNODE.Position.Y > node.Position.Y then
		-- GOING DOWN
		if SPEED <= 0.1 then
			SPEED = 0.1
		else
			SPEED -= 0.025
		end
	elseif LASTNODE.Position.Y < node.Position.Y then
		-- GOING UP
		if SPEED >= 0.5 then
			SPEED = 0.5
		else
			SPEED += 0.0125
		end
	elseif LASTNODE.Position.Y == node.Position.Y then
		-- EVEN
	end
	
	print(SPEED)
	LASTNODE = node
	NEW_SPEED = true
end

if not node then
	CURRENT_NODE = START_NODE
end

tweenRide(ride.CartNode,node)
end

wait(5)
while wait() do
if NODES:FindFirstChild("Node"..CURRENT_NODE) then
	setupRide(CARTS.Cart1,NODES:FindFirstChild("Node"..CURRENT_NODE))
else
	CURRENT_NODE = START_NODE
end
if NODES:FindFirstChild("Node"..CURRENT_NODE - 2) then
	setupRide(CARTS.Cart2,NODES:FindFirstChild("Node"..CURRENT_NODE - 2))
else
	CURRENT_NODE = START_NODE
end
if NODES:FindFirstChild("Node"..CURRENT_NODE - 4) then
	setupRide(CARTS.Cart3,NODES:FindFirstChild("Node"..CURRENT_NODE - 4))
else
	CURRENT_NODE = START_NODE
end

wait(SPEED - 0.05)
CURRENT_NODE += 1
NEW_SPEED = false
end

I know it’s really messy, I plan to simplify it at some point.
EDIT: Sorry for bugging you a bunch.

Sorry if it’s confusing, Still learning the best method’s to make this work. I really appreciate all the help so far!