Path3D: A 3d Equivalent to Path2D

Sample Projects

All of these demos are available to download here* (un-copylocked place, scripts are in StarterPlayerScripts).

* The (incomplete) witch model is for one of my own projects, so while the code for the first demo is available, the model is not


What is Path3D?

Path3D is a custom, 3d alternative to the existing Path2D instance. With it you can easily create smooth, curved paths, similar to beams. These paths can then be used in animations to control an NPC's movement, used to create paths and other models, or anything else which needs a smoothly curving line.

Overview of the Module

Full documentation of the module can be found here.

The module offers two ways to create a Path3D instance, Path3D.fromPathString() or Path3D.fromAnchorTables(). If you own the editor, Path3D.fromPathString() offers a simpler way to create Path3D instances. Alternatively, Path3D.fromAnchorTables() can be used to create Path3D instances from Vector3’s, offering an alternative if you do not own the editor. For the sake of simplicity, these demos will use Path3D.fromPathString() but details on how to use Path3D.fromAnchorTables() can be found in the documentation.

This code samples demonstrates how you can use Path3D.fromPathString() to create a new Path3D instance.

local Path3D = require(script.Parent.Path3D) --Replace with the path to the module
local PATH_STRING = script.PathString.Value --Assuming a StringValue child

local path = Path3D.fromPathString(PATH_STRING)

From there, you can simply use Path3D:GetCFrameOnCurve() to get points along the path. For example, making a part move smoothly along the path is as simple as this:

local Path3D = require(script.Parent.Path3D)
local PATH_STRING = script.PathString.Value
local PATH_CENTER = Vector3.new(0, 0, 0)
local TRACKING_PART = workspace.TrackingPart

local path = Path3D.fromPathString(PATH_STRING, PATH_CENTER)

local tweenValue = Instance.new("NumberValue")
tweenValue.Value = 0
tweenValue.Changed:Connect(function(newValue)
    TRACKING_PART:PivotTo(path:GetCFrameOnCurve(newValue))
end)

local tweenInfo = TweenInfo.new(
    5,
    Enum.EasingStyle.Linear,
    Enum.EasingDirection.In,
    0,
    false,
    0
)

local tweenGoal = {Value = 1}

local tween = game:GetService("TweenService"):Create(tweenValue, tweenInfo, tweenGoal)
tween:Play()

Additional properties and methods can be found in the module’s documentation found here.


Overview of the Editor

Path3D Editor

IMPORTANT: The editor creates a a lot of Instances in order to run properly, and if these instances are not formatted properly, they can cause issues within the plugin. As such, DO NOT delete, modify, or create any instances within the Workspace._Path3DEditorPaths folder, the plugin comes with a tool to automatically repair issues, but ideally this shouldn’t be necessary. Additionally, in order to identify different components of the editor, the plugin uses CollectionService tags, and using these tags in your own work will cause issues. All tags used by the plugin are prefixed with PATH3DEDITOR-, so this shouldn’t be a problem, but a list of tags is included below anyways.

Editor Tags
  • PATH3DEDITOR-PivotPoint
  • PATH3DEDITOR-AnchorPoint
  • PATH3DEDITOR-PriorControlPoint
  • PATH3DEDITOR-NextControlPoint
  • PATH3DEDITOR-PathFolder
  • PATH3DEDITOR-Module

Finally, the Path3D module comes with a script in order to cleanup all of the visuals that the editor creates, however, if you need to access these at runtime, this behaviour can be disabled through the EnableEditorCleanup attribute of the Path3D module.

Now on to the fun stuff.

The main dock widget of the plugin can be opened/closed through the Open button in the Plugins tab of Studio. Alongside the Open button, there is also a repair button, and I’ll go into more detail about what that does in the Paths tab section.
OpenDockWidgetButton

In the dock widget itself, there are three tabs, Actions, Paths, and Settings. The Actions tab gives you the tools to actually manipulate the Path3D instances, changing their shape and making other modifications to them. The Paths tab gives you tools to organize and rename your Path3D instances, allowing you to easily find all of your instances in one place. Finally, the Settings tab gives some settings allowing you to change the behaviour of the plugin.

Actions

Actions

The actions tab allows you to manipulate the Path3D paths, changing their shape and generating the path string.

Create Path

Create Path

This button creates a new Path3D path, parenting it to the Workspace._Path3DEditorPaths folder, or at the root of the Paths tab.

Insert Anchor Point

Insert Anchor Point

This button inserts a new anchor, either halfway between the selected anchor point and the next anchor point, or simply in front of the selected anchor point if it’s the last anchor point in the path. Anchor points are points that the path has to pass through, and adding more of them allows you to create more complicated shapes.

Add Control Points

Add Control Points

This button adds control points to the selected anchor point, either adding one or two depending on how many are missing. Missing control points aren’t an issue, and you can even delete them intentionally in order to create sharp bends between segments. Finally, the path doesn’t necessarily (and likely won’t) pass through the control points, instead, the control points determine how the path curves.

Separate Control Points

Separate Control Points

This button disables the mirroring behaviour that occurs by default when moving a control point, allowing you to move one control point without it updating the position of the other, producing a sharp bend at the anchor point.

Link Control Points

Link Control Points

This button links the two control points of the selected anchor point together, causing them to mirror each other whenever one is moved. Mirroring the control points across from each other like this typically creates smoother paths.

Link Output Value

Link Output Value

This button links the selected path’s output to the selected StringValue, meaning that whenever a new path string is generated for that path, it will also be copied to the Value property of the output value. This is helpful so that if you ever need to modify a Path3D, you don’t have to go through all of your scripts and find where the corresponding path string was stored, you can instead simply reference the output value which will automatically update whenever a new path string is generated.

Generate Path String

Generate Path String

This button generates the string representation of the Path3D which is then used in the Path3D module in order to construct Path3D instances using Path3d.fromPathString(). The generated path string is available to copied in the text box above the Generate Path String button, and it will also sent to the linked output value, if there is one. As well, the string in the text box above the Generate Path String button will disappear after 5 seconds, ensuring that you don’t accidentally copy an old path string.

Paths

Paths

This tab allows you to organize all of the paths into folders as well as renaming them, allowing you to easily sort through them.

Create Folder

TopBarCreateFolder
FolderCreateFolder

Create Folder

This button creates a new folder parented to the folder who’s Create Folder button was clicked, or the root folder if that button was clicked.

Create Path

TopBarCreatePath
FolderCreatePath

Create Path

This button creates a new path parented to the folder who’s Create Path button was clicked, or the root folder if that button was clicked.

Delete

PathDelete
FolderDelete

Delete

These buttons simply delete their corresponding folders or paths.

Hide

PathHide
FolderHide

Hide

This buttons simply hide their corresponding path or folder. Hiding a folder will result in all
sub-folders and path also getting hidden.

Renaming

PathName
FolderName

Renaming

Paths and folders can each be renamed by triple clicking on their name, then simply typing in whatever new name you would like to give them.

Re-ordering / Re-parenting

Re-ordering / Re-parenting

The order in which the paths and folders are displayed in the Paths tab can be altered by dragging the paths and folders. Additionally, the parent of any paths and folders can also be changed in this way, by dragging a path or a folder to an uncollapsed folder, it will be parented to that folder. Alternatively, if the folder is collapsed, the dragged path or folder will simply be a sibling of the other folder.

Collapsing / Expanding Folder

FolderCollapse

Collapsing / Expanding Folder

This button allows you to collapse / expand a folder, showing or hiding its contents in the Paths tab without affecting their visibility in the viewport.

Refresh Paths Tab

TopBarRefresh

Refresh Paths Tab

This button regenerates all of the frames in the Paths tab. This exists just in case a bug occurs where the Paths tab gets desynced from the actual DataModel hierarchy, and acts as an alternative to having to restart Studio. If you do encounter any bugs which result in the Paths tab becoming desynced, please let me know so that I can fix it.

Repair Data Structures

PluginsTabRepairButton
TopBarRepair

Repair Data Structures

WARNING: The Repair button in the plugins tab will proceed with a repair even if it fails to receive a ChangeHistoryService recording, this means that attempting to reverse it with undo may not work. Use of this button should be considered a last resort!

These buttons run a data fixer, attempting to restore any corrupted Path3D data structures that may be causing errors within the plugin. The Repair button in the Paths tab is preferred, as it will only proceed if it can receive a recording from the ChangeHistoryService, which means that should the repair fail, it can be easily undone using Ctrl + Z. The repair button from the Plugins tab however will proceed even if does not obtain a recording, which can be helpful if something is preventing the plugin from obtaining new recordings, or if an error is being thrown before the Paths tab repair button can be setup, but also means that you could be forced to restore a previous version of the place should the repair fail. While the data fixer repairs any instances, the Paths tab may need to be refreshed to reflect the fixes, or a Studio restart may also be required to stop any lingering errors. Finally, the data fixer is intended to stop any errors from occurring, but it may result in visual issues, such as the displayed path being different from the actual path created by the anchor and control points, but it should resolve any errors. Once again, DO NOT touch the Workspace._Path3DEditorPaths folder!

Settings

Settings

This tab contains various settings dictating the plugin’s behaviour. If you are working in Team Create with the editor, then every Team Create member should have the same settings, aside from Theme Override, as mismatched settings could cause problems, for example, control points being displayed even though Always Display Control Points is disabled.

Always Display Paths

Always Display Paths

When enabled, the anchor and pivot points of every path will be displayed even if they are not selected. This will not display paths that have been hidden in the Paths tab.

Always Display Control Points

Always Display Control Points

When enabled, control points will be displayed if any anchor or pivot point is selected within their path, not just the anchor point they are attached to. Alternatively, if Always Display Paths is also enabled, then control points will be displayed at all times, even if nothing in their path is selected. Like Always Display Paths, this will not show control points from paths that have been hidden in the Paths tab.

Enable Highlights

Enable Highlights

When enabled, Highlight instances will be used to show which anchor and control points are selected, up to a limit of 1 anchor and 2 control points. I like this as a nice indicator, but Roblox does have a limit of 31 highlights, so if you are having issues with this limit, you can disable this to prevent the plugin from using any highlights.

Pivot Point Colour

Pivot Point Colour

This determines what colour the pivot points should be, formatted as an RGB string with values from 0-255.

Anchor Point Colour

Anchor Point Colour

This determines what colour the anchor points should be, formatted as an RGB string with values from 0-255.

Control Point Colour

Control Point Colour

This determines what colour the control points should be, formatted as an RGB string with values from 0-255.

Theme Override

Theme Override

This allows you to override whether the plugin uses Light or Dark theme. By default (Disabled) the plugin will automatically try to determine what theme you are using, and it will use that theme too. If the plugin is unable to determine what theme you’re using (for example, you’re using a custom theme other than the default light or dark themes) then the plugin will default to light mode. If however dark mode would fit the theme better, you can use the Theme Override to manually set the plugin to dark mode.

Module Updates

Module Updates

Finally, the plugin also comes with a feature that will look for the Path3D module, and if it finds it and finds that it is outdated, it will let you know in the output window. This acts as a kind of interim solution at least until packages get released on the Creator Store so that you can easily know if I release any updates to the module.
IMPORTANT: This requires Auto Update to be enabled for the editor plugin, as otherwise the plugin will not know what the latest module version is.

Tips

Tips

Known Issues

Known Issues
  • When closing Studio or starting a play test session with a path selected, that path will not be hidden, and will remain visible until it is selected and deselected once more. Unfortunately, I’m not aware of any events that can indicate to a plugin when either of these occurrences are happening, so I’m not able to hide the paths before this happens. If anyone knows of an event that fires under these circumstances, please let me know and I’ll implement a fix.

Where to Get Them

The Path3D module is available for free here.
(Unfortunately I’m not able to distribute packages, as soon as I can I will update this to be a package).

The Path3D Editor is available for $4.99USD here. Note that the editor is not required to use the module, as Path3D.fromAnchorTables() provides an alternative constructor.


Other Stuff by Me

Here's some other stuff I've made

Confetti: A super simple 2D confetti effect that I made awhile ago that I thought I’d share


Closing

If you encounter any problems at all, with the module or with the editor, please let me know so that I can get them fixed as quickly as possible.
30 Likes

I can’t believe this appeared only a day before I decided to look for something like this, excellent work! I actually have a very strong use case for this sort of thing

This module is pretty cool but it feels extremely bloated. Why do you require strings instead of Vectors or CFrame, why is half of the module if statements and type-checking?

I’ll start with this first since this was a no-brainer for me.

Short answer: It makes debugging considerably easier.

Long Answer

Every time I take input from a developer, so really just any parameters passed to the module’s functions, I type check them to make sure that they won’t cause any errors later on in the module’s code. This ensures that should someone make a typo, for example, they type the wrong variable name, and instead of Path3D:GetPositionOnCurve() being passed a number, it gets passed a string from some other random variable. If I didn’t type check this, then when that code ran, they would get an output in the console saying something like “Attempt to perform arithmetic on number and string,” and an error pointing to a line of code within the module, even though the mistake is outside of the module. This isn’t great for debugging, as the error makes it seem like there’s some kind of mistake in the module, and the message doesn’t even remotely relate to the actual error that was made. By type checking all parameters first though, I can throw my own custom errors, pointing to the line of code that actually caused them. In this case, instead of getting something like “Attempt to perform arithmetic on number and string,” you would actually get “Unable to invoke Path3D:GetPositionOnCurve with given t value, expected number, got string,” something that tells you exactly what the mistake was. Not only that, but it also reduces the amount of people mistakenly believing that there’s something wrong with the module, reducing the amount of false bug reports I get.


Additional Context: This was posted before update 1.1.0, and Path3D.fromAnchorTables() did not exist. Since v1.1.0 however, Path3D.fromAnchorTables() is available which uses Vector3’s.

This was a bit more complicated, and I still go back and forth a bit on this.

Short answer: I thought it would make it easier for people to use the module who didn’t own the editor, but I’m open to providing an alternative.

Long Answer

As I said, I’m still going back and forth a bit on this, as I completely agree, using strings does feel a bit weird. In an ideal world, I’d create a new Instance that would exist in the DataModel hierarchy, but to my knowledge that isn’t possible, making any other possible solutions messier. Because of the editor, I needed something that could be generated and then used in multiple places, but I don’t think this really limited it too much. While in hindsight I could have used some form of structure using Vector3 and CFrame values, I wanted to make sure that the module was still easy to use for people who didn’t own the editor, and I think the specific naming and hierarchy of this would’ve been pretty convoluted. Ultimately that left with me with strings, which although not perfect, I tried to keep the formatting of as simple as possible. With that said however, internally the module does use Vector3’s, so if you or others wanted some other constructor that made use of Vector3’s instead, it wouldn’t be too hard for me to implement. I left this out of the module initially because the path strings aren’t too hard to generate from from Vector3’s or CFrames, but if anyone would like this please let me know and I’d be happy to implement it.


On an unrelated note, you seem to have made a few posts on the dev forum, do you have any idea why my links weren't working? I've got one of the broken ones still at the top of the module's section, and it's a direct copy-paste of the one at the end.

Interesting. You’ve done a lot of work here, so I assume it’s performant. I’ll bookmark this page, as I might actually use it. Saves quite a bit of time.

I haven’t actually read properly all the way through your post, so you may have already answered what I’m going to ask; Can you trigger it whenever you like? So say for instance; the second clip, if a player walks out of a blacked-out building right, it plays. When they go in, it stops, and all the moving objects during the Path3D animation get removed (unrendered).

If you’re familiar with how Path2D works, this is the same. The main thing that the module provides is simply Path3D:GetPositionOnCurve(), the animations in the demos are simply me tweening a NumberValue, and then calling Path3D:GetPositionOnCurve() whenever it changes. So in order to stop it, all you would have to do is stop that tween, clean up the NumberValue that was being tweened, and remove whatever part you’re moving. As well, the source code for the demos is available in an un-copylocked place (link right beneath them) if you’d like to check it out more.

Regarding performance, while I haven’t put much thought into it, the module isn’t doing anything complicated. The only thing I would be slightly concerned about is the initial calculation of the Path3D’s length, but that only happens once for each Path3D (and I don’t think that even is a problem).

How am I supposed to make my own path string? It’s basically forcing me to use the plugin

1 Like

Additional Context: This was posted before update 1.1.0, and Path3D.fromAnchorTables() did not exist. Since v1.1.0 however, Path3D.fromAnchorTables() is available which uses Vector3’s.

I’ve got a full breakdown of the formatting of the path string in the documentation, but I’ve been considering an alternative constructor using Vector3’s, so if you’d be interested in that please let me know. Internally the module uses Vector3’s, so it I don’t think it’d be too difficult.

2 Likes

The plugin doesn’t show itself, the script is disabled.

Sorry, could you please elaborate on that, I’m not sure what you mean. Are you having issues with the module, is the editor panel not opening, are you unable to find the editor’s paths folder, something else?

Your plugin’s script is disabled.
Pictures of the plugin inserted into workspace via insertservice after purchasing:
image
image

Sorry about that, should be fixed now. Thank you for letting me know!

1 Like

Path3D v1.1.0

I’ve just released v1.1.0 for the module, with the main additions being Path3D.fromAnchorTables(), Path3D:GetRotationOnCurve(), and Path3D:GetCFrameOnCurve(). A full changelog and further information on each of these methods is available in the documentation.

Path3D.fromAnchorTables()

This method offers an alternative constructor to Path3D.fromPathString() using Vector3’s, making it easier to construct Path3D instances if you don’t own the editor.

Path3D:GetRotationOnCurve()

This method offers a way to get the rotation or tangent on curve, removing the need for any weird “look aheads” and the weird problems those had at t=1.

Path3D:GetCFrameOnCurve()

Similar to Path3D:GetRotationOnCurve(), this bundles together Path3D:GetPositionOnCurve() and Path3D:GetRotationOnCurve() into a single method call, making it easier to have parts that change their orientation to follow the path.

More Too!

There’s also been a couple other minor tweaks which can be found in the changelog.

Closing

As usual, please let me know if you encounter any issues and I'll fix them as quickly as I can. As well, I'm also working on an update to the editor, allowing you to rename, group, and hide paths, as well as a warning if you're using an outdated version of the module, at least until packages on the creator store get released. Enjoy!

Sorry, I just realised I forgot to enable v1.1.0 for distribution on the Creator Store, if you were previously unable to get the latest version, the links in the main post should now be working. Sorry about that!

1 Like

Path3D Editor v2

I've just released version 2 for the Path3D Editor plugin, fixing a couple of old bugs and adding the Paths tab, a single place to organize and your Path3D instances. I've updated the original post with more info on the editor and its new features, and I've also included more videos of its features.

Module Update Warnings

The editor will now automatically warn you if you're using an outdated version of the Path3D module, however Auto Updates must be enabled for this to work.

Paths Tab

The module now has the new Paths tab, which along with the new Folders allows you to better organise your Path3D instances.

Dark Mode

The editor now supports dark mode! Unfortunately, the editor doesn't support custom themes other than the built in light and dark modes to studio, but you can manually specify which theme to use if the automatic theme chooser isn't working.

Full Changelog

Changelog
  • Added a warning when using an outdated version of the Path3D module
  • Added a repair tool for repairing any corrupted data structures that the plugin needs (for example, anchor points missing children, pivot points with non-sequential anchor points, etc.)
  • Split the dock widget into three tabs, Actions, Paths, and Settings
  • Added a new Paths tab
  • Added support for dark mode
  • Added support for paths nested within folders in Workspace._Path3DEditorPaths
  • The selection cubes (the things that let you click on a path to select it) now get hidden when selecting a path, meaning that they will no longer get in your way when you’re trying to drag anchor or control points around
  • Fixed a bug where the Generate Path String button wouldn’t darken when hovering over it
  • Fixed a bug where inserting an anchor point in between two anchor points and then separating the control points would cause the beam connecting to the prior anchor point to not update properly (no idea what that means but I had it in my Google Doc as a fix so it’s getting included here)
  • Fixed a bug where clicking Link Control Points with no control points selected would leave the control points unmirrored until either one of them was moved
  • Fixed a bug where pivot, anchor, and control points wouldn’t have their events connected if they were created by another Team Create user
  • Fixed a bug where clicking Add Control Point with only a control point selected wouldn’t create a new control point (you had to have the anchor point selected too)
  • Fixed a bug where undoing the deletion of a control point would sometimes cause visual inconsistencies in the shape of the path
  • Fixed some typos in the original post
  • Updated the Path3D demos to use v1.1.0 of the Path3D module