SimpleSpline (V1.1)




SimpleSpline is a open source module that creates spline objects easily by using CatRom

This module works by creating a spline based on the points you pass through

Example Usage

local Points = {CFrame.new(0,0,0), CFrame.new(0,5,20), CFrame.new(24,0,40)}
local Spline = SimpleSpline.new(Points, 0.5, 0)

Spline:SetOptions({
    Uniform = true,
    Offset = CFrame.new(),
    Loop = true,
    Reverse = false
})

Spline:Visualize()

local Object = -- Your object to move along the spline
local Speed = 20 -- or you can use: Spline:GetSpeedFromTime(Seconds)

local Path = Spline:FollowPath(Object, Speed)

Path.NodeReached:Connect(function(Node)
	print("Reached node",Node)
end)

Path.Completed:Connect(function()
	print("Finished path")
end)

Example Video

ezgif-2-abb85941db


The documentation is on GitHub

Links:

83 Likes

Hey Mewious why not use Moonwave or something else for documentation? And maybe make a Wally packages? Would make more sense since I’m pretty sure one of the intended use for this is with Rojo, cool stuff though.

7 Likes

Version 1.1

Changes:

  • The FollowPath function can now take in a table of objects you want to move
    Spline:FollowPath(Objects,Speed,Distance)

  • Added
    Path.GetElapsed()

  • Added
    Path.PathCompleted – this will fire when all the objects finished the path

2 Likes

How did you come to this conclusion?

3 Likes

Most managed projects using Rojo, use Aftman for tooling and Wally for managing packages. They just make it easier, with making handling dependencies easier. However it might need to be changed, as init.lua refers to Catrom as script.Catrom, however Rojo does not seem to support Scripts inside Scripts, without modifying the project.json.

Update: After a few months of Rojo usage I have realised that it does support script inside scripts and the module will not be needing any changes.

3 Likes

wowzers this is so cool!!!
thamks mew

1 Like

This is probably my favorite spline module available, however there’s something I’ve been trying to solve. Is there any way to get the tangents(?) to always point outwards? You can see here how I’d ideally like the red to always be facing the ‘outside’, however it flips when crossing between upper/lower sections of the spline. I can’t figure out what to change to get it to work the way I’d like

EDIT: I managed to implement this myself by hacking apart some of the code in the solveUniformCFrame area. It’s not a good solution but it’s where you might look if you want to align your spline’s orientation for something like a ferris wheel or tracked vehicles

local pos = spline:SolveUniformPosition(splineT)
local vel = spline:SolveUniformVelocity(splineT) --these two can probably be combined further to optimize
local LocalVec = ReferencePart.CFrame:VectorToObjectSpace(vel)
local rad = math.atan2(LocalVec.Z,LocalVec.Y)
cf = CFrame.new(pos) * CFrame.fromEulerAngles(a,b,c) * CFrame.Angles(rad+halfpi,0,0)
2 Likes


This module has been great so far and I’ve been using it for numerous things, however I believe I found an issue. Using ChangeSpeed messes with the distance between parts. You can see here I start at speed 60 and after 2 seconds I use ChangeSpeed to 1 and it resets everything and messes with the spacing. It would also be nice to have a way to pre-distribute parts along the path so you can stop their movement and resume it from the same location for something like a roller coaster.

2 Likes

Will take a look into this! thanks

This seems super useful but is there a way to make it not rotate while it moves? I’ve been looking everywhere for something that can and even trying to edit some of this code but I don’t know enough lua and can’t find anything to help.

A hacky way you could do this is use an invisible part on the track and then every frame set the position of your other part to it

Your best bet is to edit the code tho

I looked at the code and still couldn’t figure out what I need to change because I don’t know enough lua, do you know of any other things I could use that can move a part smoothly like this one? (without rotating I mean)

Like i said, use an invisible part and then place your object on it.

Local script

local object = path.to.object
local objectOnPath = path.to.object2
local orientation = object:GetPivot() orientation -= object.Position
game:GetService("RunService").RenderStepped:Connect(function()
object:PivotTo(CFrame.new(objectOnPath.Position), orientation)
end)

this also preserves the original orientation of the object you want to move

This would work but the way I have it set up is so the script has to be under a model in workspace, so it isn’t running, unless there’s some other way to run it. (Sorry if I’m missing the obvious by the way, I’m not very good at scripting)

Even now, I’m still trying to figure out how to change the actual speed of the object without messing with the Time Value of it.

1 Like

Im also having issues with ChangeSpeed, if I change the speed of a path to lets say half then the objects get teleported back, it also doesn’t update the NodeReached event so it fires node reached even though it hasn’t reached a node yet.

My solution would to just use BezierPath, SimpleSpline seems to not be updating anymore.