Smooth Path package

Name: Smooth Path

The Smooth Path package allows you to define a path of points, and have entities smoothly curve along those paths. The curves are calculated automatically, so all you need to do is set up the path points. The entity that follows the path must have a smoothPathFollowerScript on it, where you can define a path, speed, and rotation type.

Two example paths are provided, called SmoothPathExample_FollowTarget (where the follower faces towards the central target) and SmoothPathExample_RotateAlongPath (where the follower faces the direction it is moving along the path).

There is also a PathSpeedAdjuster script folder that you can attach to the User or Player template. Here, you can select a path follower to control, and it allows you to adjust the speed of the path follower by holding a button. Alternatively, you can set the speed of the path follower when it reaches different points along the path, by adjusting properties on the path points themselves (explained below).

Functions to use
These functions are on the smoothPathFollowerScript.

Move(bool loop)
This will tell the smooth path follower to move along the path at its given speed. It can be called on server or client, but will only run if the “runOnClient” property is set to match where it’s being called. The “loop” argument tells the path follower whether to keep looping around the path. By default, it will run the path once.

Stop()
This stops the path follower from moving. It will remain in position. It can be called on server or client, but will only run if the “runOnClient” property is set to match where it’s being called.

Reset()
This stops the path follower using the stop function above, and then also returns it to the position and rotation of the first path point, ready to go again.

SetPath(entity path)
This assigns a new path for this path follower to follow. This could allow a set of paths to be used with decision points in between, and when the player makes a decision, you can use this function to set the next path to follow, and then call “Move” to move along the next path.

SetSpeed(number speed)
This sets the speed of this path follower. You can use this to speed up and slow down the path follower (see the “pathSpeedAdjuster” script in this package for an example). If used with EstimateTotalDistance() and GetDistance(), you can use this to have the path follower accelerate at the start of its path, and decelerate to a stop at the end, which is how the ghost train in the Dark Circus Hub works.

EstimateTotalDistance()
This will return a rough estimate of the total distance along the path, in cm. You can use this in conjunction with the GetDistance() function to work out how far along the path this follower is. Can be called on server or client.

GetDistance()
Returns the distance this follower is along its path, in cm. Must be called in the same place as the path follower is moving (server or client) otherwise this will return nil.

Path point properties
Each point along the path has a “smoothPathPoint” script attached, where you can allow the point to adjust the path follower’s speed.

setSpeed - whether or not this point will set the path follower’s speed.

pointSpeed - the speed to set the path follower to at this point.

setSpeedSmooth - if ticked, the path follower will transition towards this speed, between the previous path point and this path point. If unticked, the path follower will instantly set this speed on reaching this path point.

7 Likes

Hi Adam, this is such a useful package and I’m going to start using this more.

Is there anyway I can have it only do the 1 loop, and not run at start? I want to have it start on interact but just go around once. It only seems to give me the option to turn off the infinite looping if I have it do an automatic loop at the beginning and I want everything to have a chance to load in first.

So I don’t want anything to run until the player interacts, then just do the 1 loop and coming to a complete stop at the end ready for the player to interact again.

Thanks.

Give it a go now, I realised what the issue was and fixed it so you should be able to play on start, once or looping and play on interaction (or any event), once or looping. Just update the package.

In case you’re interested in what the bug was, this is the function declaration (i.e. the start of the function) that you use to make it move:

function SmoothPathFollowerScript:Move(loop)

It’s intended to take a boolean (true/false) value there, which is passed to it correctly if it’s started automatically.

However, if you use a built-in event like OnInteract, those events pass the player entity as an argument to the function they call. That means Move was being called with the player as the loop argument. To loop it, I was just check if loop which passes if loop is true, but also passes if it’s a non-nil object, i.e., the player entity. So now I’ve added a bit to check the type of the loop argument and just use the self.properties.loop value if a proper boolean wasn’t provided. Like this:

if loop == nil or type(loop) ~= "boolean" then
	loop = self.properties.loop
end

Hopefully that makes some sense and gives you a bit more insight into how bugs can come up and how to fix!

1 Like

Thanks again Adam, just tried it out and it works exactly how I wanted it too. Me and SinJin both had a look at changing the code but couldn’t figure out why the option didn’t always show. Your description does make sense and I’m aiming to get to the stage where I’m able to find the bug like you did. Thank you very much.

Oh yeah, I also had a bit in the loop property which would hide it if you unticked playOnStart but I can’t remember my logic for including that!
For reference, it looks like this:

{name = "loop", type = "boolean", visibleIf=function(properties) return properties.goOnStart end}
1 Like

Hey Adam, you’re package is amazing :slight_smile:
Would it be possible to add a script that we could put on any locator of the path.

This script would be used to set the speed of the follower when reaching the locator.

This is an excellent suggestion. I’ve built it in as properties on the “SmoothPathPoints” themselves. You can set whether the points will set the path follower’s speed, and whether they set it smoothly (i.e. it goes towards that speed as it approaches the point). Should make a big difference.

3 Likes

Amazing ! Thank you so much for that, it will be very useful !

1 Like

vroom vroom )
Thanks for the package )

1 Like