Simple Waypoint System (SWS) - Move objects along paths

I can't send you any data, but I have managed to isolate which script is doing it. HoMove produces the weird rotation behaviour, but iMove does not. If I use iMove the object follows the path perfectly and never tries to rotate itself. If I use hoMove on the same path, the object randomly rotates on Z mostly, but sometimes X and Y as well.

I know that the lock-axis option produces trouble in certain situations, but it's difficult to debug without any further data. Most likely it behaves incorrect when using different heights for the waypoints, however that seems not the case here. I'll see what I can do, though.

A parent of my vehicle object had a rigid body physics controller on it, I think the path was conflicting with the controller. Since removing it, the path has been perfect in both iMove and hoMove. I will post again if the problem appears again.

the Path Manager component already displays a "straight path length". This is useful in case you use iTween for straight movement. If not, in HOTween there's the alternative to find out the duration of the tween via myTweener.duration (read-only property). You could debug this at the end of hoMove's Move() method, where the tween gets created.

the Path Manager component already displays a "straight path length". This is useful in case you use iTween for straight movement. If not, in HOTween there's the alternative to find out the duration of the tween via myTweener.duration (read-only property). You could debug this at the end of hoMove's Move() method, where the tween gets created.

Click to expand...

I intend to use curved paths, so I guess the latter option is the one I should look at then. Is either iTween or HOTween capable of changing movement speed while on a path? Can't test this myself at the moment, but I guess it's possible judging from the user controlled path movement example...?

Unfortunately not. The user controlled capsule uses iTween's PutOnPath() method and therefore does not create a tween at all, for changing the speed of a tween you would have to destroy and recreate it every time... Recreation is a bit difficult with my HOTween implementation though, because HOTween inserts a controlpoint at the position it starts tweening by default, this could cause weird stutter or position jumps.

Edit: You could also download the full source code of HOTween (and maybe donate a buck at the same time? ), its PlugVector3 path implementation has a way to retrieve a time - length table

Edit2: Daniele, the knightly author of HOTween, just reminded me that changing the speed of a tween is indeed possible (totally forgot that, because I only thought about movement speed) using the tween.timeScale variable. You would just have to set the movement speed accordingly then, so it does not revert when it's finished.

Edit2: Daniele, the knightly author of HOTween, just reminded me that changing the speed of a tween is indeed possible (totally forgot that, because I only thought about movement speed) using the tween.timeScale variable. You would just have to set the movement speed accordingly then, so it does not revert when it's finished.

Click to expand...

My idea was to have an object on a path that slows don to a halt when the user presses a button and accelerates back to its standard speed on release. Or maybe just stopping and restarting if a gradual speed change is out of the question.

My idea was to have an object on a path that slows don to a halt when the user presses a button and accelerates back to its standard speed on release. Or maybe just stopping and restarting if a gradual speed change is out of the question.

Click to expand...

Sorry if I intrude, but I have an idea about how that could be done

You could store a variable (a float of value 1) that represents the timeScale of the path tween. Then:
- you create and store an HOTween Tweener (let's refer to it as myTSTween) that animates the variable to 0, and keep it paused
- when the user presses the button, you play myTSTween, and use its OnUpdate callback to update the path animation's timeScale, based on the changed timeScale variable
- when the user releases the button, you revert myTSTween (myTSTween.Reverse()) and play it backwards, still using the same OnUpdate callback to revert the timeScale of the path animation

You could store a variable (a float of value 1) that represents the timeScale of the path tween. Then:
- you create and store an HOTween Tweener (let's refer to it as myTSTween) that animates the variable to 0, and keep it paused
- when the user presses the button, you play myTSTween, and use its OnUpdate callback to update the path animation's timeScale, based on the changed timeScale variable
- when the user releases the button, you revert myTSTween (myTSTween.Reverse()) and play it backwards, still using the same OnUpdate callback to revert the timeScale of the path animation

Click to expand...

Sounds like a plan. I'll see if I can come up with a prototype tomorrow.

hoMove's HOTween Tweener is named "tween", stored as a private variable. You can access its timeScale property via tween.timeScale = ...; There is no built-in method in hoMove for controlling the timescale at this point.

hoMove's HOTween Tweener is named "tween", stored as a private variable. You can access its timeScale property via tween.timeScale = ...; There is no built-in method in hoMove for controlling the timescale at this point.

edit: mkay

Click to expand...

Yes, I just didn't figure out until I noticed tween was set private rather than public. Thanks anyway.

Seems like I need two Tweeners since I can't seem to reverse the myTSTween once it has completed, though. Maybe I just forward this particular issue to Izitmee since the SWS part of my scene works fine.

Just in case anyone is interested, I needed to use SWS in a menu screen while the game was paused using Time.timescale = 0f;

As far as I can tell, there is no way to access that iTween feature within SWS. (iTween has a command called ignoretimescale) that allows you to bypass timescale specifically in cases where you may want to use an iTween during game pause, for menus etc.)

The iMove script seemed to be the best place to put a public variable that would allow this. This also lets me control this on a per gameobject basis. So I can have some waypoint objects adhere to timescale and others not.

At the top of iMove.cs, I placed:
public bool ignoreTimeScale = false;

then in the Move method in iMove.cs, I simply added another itweenHash.Add statement as follows:
iTweenHash.Add("ignoretimescale", ignoreTimeScale);
Then I just set the bool to true in the inspector on that object and it works great.

This takes advantage of the built in feature in iTween "ignoretimescale" and adds it to the hash used by your gameobject with the iMove script.

you're right, there is no ignoretimescale option in SWS.
I intentionally programmed iMove as it is, since I can't add checkboxes for all features of iTween.
Glad you found out where it belongs and thanks for sharing!

If you haven't bought Simple Waypoint System yet, now you can also purchase it through our online store,
which sends you a generic download link at the time of purchase, that always points to the latest version.

I'm really excited for this release, because now your objects can actually leave their paths!
I implemented a new settings field for custom messages, so you are able to program every possible interaction or behavior at a waypoint. You could stop the movement at a waypoint, turn on Unity's pathfinding or let the object look around, move it back to the waypoint and continue its path. The list goes on!

Here is the complete changelog.

Fixes Changes

• hoMove: removed critical waypoint distance value that led to unexpected behavior when tweening an object with a very high speed value or timescale
• hoMove: completely rewritten to incorporate with partial tweens. The tween and its runtime checks should be a significant amount faster now
• hoMove: partial tweens allow easing options between waypoints instead of an easing curve for the whole path
• hoMove: separated MoveToPath and its internal ClosePath option, you can toggle them independently now as ClosePath has its own checkbox
• hoMove: movement parameters (waypoint positions) do not update at each iteration anymore, you have to call InitWaypoints() and recreate the tween manually with StartMove(), for example at the last waypoint using messages
• simplified the Waypoint Manager even more, it shows only one button now
• switched widget position. You’ll find the Waypoint Manager setup widget under “Window > Simple Waypoint System” and iMove/hoMove under “Component > Simple Waypoint System”
• documentation updated, contact info email changed​

Features

• iMove/hoMove: custom methods callable per waypoint. Both editor scripts for iMove/hoMove were changed accordingly, so that this feature comes with a new message settings field, easily adjustable by the user
• custom methods are using SendMessage() and allow one parameter of the type object, text, numeric, vector2 or vector3. The class of these types was centrally placed in WaypointManager.cs
• new example script “MessageExample.cs” demonstrates the usage of custom messages in the scene “Example_Straight” on walker “Capsule4”
• hoMove: integrated HOTween’s new lock-position option that limits movement on the selected axis​

A special thanks goes to Daniele and his incredible work on HOTween, without whom this update would not have been possible.

Wow, awesome list of additions! It's impressive how SWS grew in just a few weeks: if that's not awesome support I don't know how to call it. Plus, I know I might appear as an Inspector maniac, but the new and improved waypoint Inspector looks so sexy!

Hey Baroni -
I purchased SWS but haven't had the opportunity to use it yet. What I'd like to do with it (eventually) is have it control vehicles within my game. I've done this before in other languages, but the visual structure of SWS I hope will make things easier to do at design time.

Anyway, let's say I have four paths - A, B, C, D. When the object hits the last waypoint of Path A, I'd like for the object to randomly choose from path B, C, or D to continue on it's way. Think of a four-way intersection, and a car can choose from turning left, right, and forward (but still has to move between the last waypoint of the previous path and the first waypoint of the new path).

Anyway, let's say I have four paths - A, B, C, D. When the object hits the last waypoint of Path A, I'd like for the object to randomly choose from path B, C, or D to continue on it's way. Think of a four-way intersection, and a car can choose from turning left, right, and forward (but still has to move between the last waypoint of the previous path and the first waypoint of the new path).

Click to expand...

Hi anwserman,

this behavior should be easy to program with the newly implemented message settings. What you want to do first, is to write a small method, attach the script to your vehicle and assign the created method to the last waypoint in the message settings of that vehicle. Now your vehicle should call an empty method at its last waypoint.
Next, you have to choose a path (B, C, or D) in that method. You could hardcode the path names in a string array and randomly choose one slot. Then, call the vehicle's SetPath() method (you need a reference to iMove/hoMove) with the corresponding PathManager parameter like this:

Depending on your use case, make sure that you set the variable "MoveToPath" of iMove/hoMove to true before calling SetPath(). This will ensure that your vehicle moves to the path before following its waypoints.

this behavior should be easy to program with the newly implemented message settings. What you want to do first, is to write a small method, attach the script to your vehicle and assign the created method to the last waypoint in the message settings of that vehicle. Now your vehicle should call an empty method at its last waypoint.
Next, you have to choose a path (B, C, or D) in that method. You could hardcode the path names in a string array and randomly choose one slot. Then, call the vehicle's SetPath() method (you need a reference to iMove/hoMove) with the corresponding PathManager parameter like this:

Depending on your use case, make sure that you set the variable "MoveToPath" of iMove/hoMove to true before calling SetPath(). This will ensure that your vehicle moves to the path before following its waypoints.

Please let me know if you need further help.

Greetings,
Baroni

Click to expand...

Hey Baroni!

Thanks for your reply! Anyway, I've always just had the vehicles decide when to accelerate or decelerate, they alone never chose paths. If they'd go to a traffic light, the vehicle would randomly get a new path if the light was green or brake if red. This could be easily implemented via triggers. But knowing that this new feature enables movement between paths is great.

Since we're on the topic, do objects on a path have tge option of rotating with the path, and if so how does aligning to the ground work with such a feature?

I've always just had the vehicles decide when to accelerate or decelerate, they alone never chose paths.

Since we're on the topic, do objects on a path have tge option of rotating with the path, and if so how does aligning to the ground work with such a feature?

Click to expand...

Hi anwserman,

just a small hint on the first line: you can control the speed of a tween using its timescale property (described on the HOTween docs).

Rotating with the path is an option built-in long time ago There's a checkbox in the inspector for iMove/hoMove named "Orient To Path". Regarding the second issue: per default, your object will follow the height of each waypoint, that means if you align the waypoint to the ground, your vehicle will simply follow it. The "Size To Add" value in the inspector adds an additional height to the car (typically you type in the half of your object's height), so the vehicle "stands" on the path. There's also a selectable field "Lock Rotation" to lock the rotation on one axis so it does not tilt to a side. Unfortunately there is no built in setting that allows rotation around a corner (to lift the wheels) and uneven terrain is a bit critical, but maybe I misunderstood what you want to achieve?

I think I got it - I'm currently implementing the core gameplay right now (what's the point of having vehicles running around if the main aspect of gameplay isn't implemented?!?). I'll take a break from working on my game input (and backing it up!) and start trying with SWS.

Basically, I would like the vehicle to rotate on the X/Y axis and ignore the Z axis. So the vehicle will slope forward/backward when going up hills and turn left/right when turning, but NOT bank on the z-axis.

-Jeff

EDIT: Baroni, I found a bug in SWS! I'm so sorry! I'll re-edit and post a video once I get one uploaded.

Anyway, here's what happens, Scenario 1:
1) Object is moving between paths (using the Move to Path feature)
2) Object's speed is set to 0, object keeps moving to the first node of the new path and then stops

Anyway, here's what happens, Scenario 2:
1) Object is moving between paths (using the Move to Path feature)
2) Object's speed is set to 0
3) iMove.Stop() is called
4) Object stops
.... some time passes ...
4) Object's speed is set higher than zero (let's say 6)
5) iMove.StartMove() is called
6) Object moves at a snail's pace (even though the speed value says 6) until it hits first node, then moves normally

I seem to be having a bit of a problem playing an idle animation... or maybe I'm just doing it wrong. I want my character to pause for 5 seconds at waypoint 1. However, I always get an error message saying that the idle (or any other) animation can't be found. I can select it just fine in the the Inspector, but it doesn't want to play. All my animations are different FBX files containing the skeleton of the main character doing different things, is that the problem?

EDIT: Baroni, I found a bug in SWS! I'm so sorry! I'll re-edit and post a video once I get one uploaded.

Anyway, here's what happens, Scenario 1:
1) Object is moving between paths (using the Move to Path feature)
2) Object's speed is set to 0, object keeps moving to the first node of the new path and then stops

Anyway, here's what happens, Scenario 2:
1) Object is moving between paths (using the Move to Path feature)
2) Object's speed is set to 0
3) iMove.Stop() is called
4) Object stops
.... some time passes ...
4) Object's speed is set higher than zero (let's say 6)
5) iMove.StartMove() is called
6) Object moves at a snail's pace (even though the speed value says 6) until it hits first node, then moves normally

Click to expand...

Hey Jeff,

thanks for recording a video! You're right, iTween updates its parameters (speed value) only at every waypoint, there is no way to change parameters of a running ( i- ) tween. That's an iTween thing. I suggest you use the hoMove component for smooth movement of your vehicles. hoMove utilizes HOTween behind the back and allows curved paths since version 2.0.

As mentioned above, you can get the tween of hoMove (declare the "tween" variable as public first) and control the speed using its timescale property. This would get rid of scenario 1, because if the timescale of the tween is zero, the tween does not run further. You could also call Pause() and Resume() on the hoMove component to achieve the same result.

That would be very similiar to scenario 2, where Pause() and Resume() could stop and resume the tween at the stop light. (nice colorful box btw ) Again, using the timescale property and perhaps a coroutine for acceleration and deceleration could give a desired result. Let me know your progress on this.

However, I always get an error message saying that the idle (or any other) animation can't be found. I can select it just fine in the the Inspector, but it doesn't want to play. All my animations are different FBX files containing the skeleton of the main character doing different things, is that the problem?

Click to expand...

Hi nielsvaes,

no, that should not be a problem, thanks for the screencapture. By investigating your object, "Gerrit Mover" has no animation component attached, that's fine. But the animation clips have to be assigned to an object, does the gameobject "Character_Gerrit" have these animation clips assigned like at this page? http://docs.unity3d.com/Documentation/Components/class-Animation.html

If yes, please expand the FBX animation file and try to directly drag the animation clip in the "Idle Anim" slot instead.
Hope that helps,

thanks for recording a video! You're right, iTween updates its parameters (speed value) only at every waypoint, there is no way to change parameters of a running ( i- ) tween. That's an iTween thing. I suggest you use the hoMove component for smooth movement of your vehicles. hoMove utilizes HOTween behind the back and allows curved paths since version 2.0.

As mentioned above, you can get the tween of hoMove (declare the "tween" variable as public first) and control the speed using its timescale property. This would get rid of scenario 1, because if the timescale of the tween is zero, the tween does not run further. You could also call Pause() and Resume() on the hoMove component to achieve the same result.

That would be very similiar to scenario 2, where Pause() and Resume() could stop and resume the tween at the stop light. (nice colorful box btw ) Again, using the timescale property and perhaps a coroutine for acceleration and deceleration could give a desired result. Let me know your progress on this.

Click to expand...

I looked into HoTween and I figured out that I can't use tweening at all, unless my mental math is wrong (I've been hammering it hard the last few days hah). There's no simple way of doing it, by changing a normalized timescale value between 0-1 means that the vehicle will move at a speed dependent on the space between checkpoints.

Instead, what I did is figured out how you implemented your checkpoint system I took the difference in position between checkpoint(n) and checkpoint(n + 1), normalized it, and move any gameobject on it by gameobject.transform += (differenceVector * speed * time.deltatime). For rotation between points, I use iTween's LookTo feature.

If you're interested, I'll clean up and comment my code and post it - or send it to you! If you like it, I'd love to clean it up and send it to you as a package. I have it designed to where you can drag a script onto an object and it starts tweening (like yours) but also an additional script that when trigger boxes collide, will assign a new path to a tween or change it's state - like braking.

I looked into HoTween and I figured out that I can't use tweening at all, unless my mental math is wrong (I've been hammering it hard the last few days hah). There's no simple way of doing it, by changing a normalized timescale value between 0-1 means that the vehicle will move at a speed dependent on the space between checkpoints.

Click to expand...

I don't know if I fully understand what you are trying to do, but I did a small test project using timescale settings in HOTween to brake/accelerate a vehicle a week or two ago just fine. I set the SWS tween to speed instead of time to avoid speed differences when moving between checkpoints. Have you tried to use speed instead of time?

Yeah, I used speed instead of time, still the same problem (except it went around curves). The speed also didn't change until it went to a new checkpoint, which I found odd. But anyway, I still got it working (regardless), so the point's still moot lol.

no, that should not be a problem, thanks for the screencapture. By investigating your object, "Gerrit Mover" has no animation component attached, that's fine. But the animation clips have to be assigned to an object, does the gameobject "Character_Gerrit" have these animation clips assigned like at this page? http://docs.unity3d.com/Documentation/Components/class-Animation.html

If yes, please expand the FBX animation file and try to directly drag the animation clip in the "Idle Anim" slot instead.
Hope that helps,

Regards,
B.

Click to expand...

I just opened this page to let you know I found the problem, didn't expect a reply so soon Anyway, you were right, I scaled the animations array of Character_Gerrit down to just 1, which held the walk animation.

Instead, what I did is figured out how you implemented your checkpoint system I took the difference in position between checkpoint(n) and checkpoint(n + 1), normalized it, and move any gameobject on it by gameobject.transform += (differenceVector * speed * time.deltatime). For rotation between points, I use iTween's LookTo feature.

Click to expand...

That seems uber complicated

Could you pm me your package and a short explanation on what you are trying to do?
Maybe I'll get it running without math, as c-Row confirmed. Complicated code isn't the best way in the long run.

I'm really excited for this release, because now your objects can actually leave their paths!
I implemented a new settings field for custom messages, so you are able to program every possible interaction or behavior at a waypoint. You could stop the movement at a waypoint, turn on Unity's pathfinding or let the object look around, move it back to the waypoint and continue its path. The list goes on!

Click to expand...

I'm still a little bit foggy about this. Where do you need to add these methods in order execute these? Can you place them anywhere? Do you need specific scripts with specific names in specific locations?

In our game, we want to have the character walk from waypoint1 to waypoint 5. He needs to stop at waypoint3 and a specific animation needs to play there. Once that animation is done, the character needs to continue to waypoint 5.

How exactly do I need to set this up? Let's say I have an animation called "dancing". Do I just need a script with

I'm still a little bit foggy about this. Where do you need to add these methods in order execute these? Can you place them anywhere? Do you need specific scripts with specific names in specific locations?

Do I just need a script with [...] and then use "StartDancing" as a method name on waypoint 3?

Click to expand...

It's nearly as simple as that You can look up a message sample in the scene "Example_Straight", where a capsule flies through the air.
From the changelog:

new example script “MessageExample.cs” demonstrates the usage of custom messages in the scene “Example_Straight” on walker “Capsule4”

Click to expand...

Basically you create a script and attach it to your walker object. Name it whatever you like. Then you create a method within this script, let's call it "StartDancing" as in your post. At the desired waypoint, type in the name of this method in the message settings.

Regarding the method: In this case, you want to pause the tween at the third waypoint, play the animation and resume the tween after the animation fully played through. There are two different approaches for pausing a tween, depending on the movement script. For iMove, you would use:

Does this system automatically puts the character on the right Y-axis? Or could you give me a little more information about the moving object/character placement?

Click to expand...

Hi wmgcata,

it puts the character on the path you created in the editor. The path could be 2D, 3D with Y-up, Z-up or something else.
The first thing you would do is to create a path in your scene. Then, you rotate your object how you need it to be and attach a movement script to it. It will then simply follow the path assigned to it. There are no limitations regarding world axes. Did I answer your question?

edit: the rotation of the object would stay the same on the whole path. If you need your object to rotate while moving on the path (maybe climbing a wall), there can be a bit of scripting involved.

Could you pm me your package and a short explanation on what you are trying to do?
Maybe I'll get it running without math, as c-Row confirmed. Complicated code isn't the best way in the long run.

Click to expand...

Hahaha, it's not really that bad. I'll message it to you when I get the chance - I've actually coded this before in other languages, and this is the first time I got it working in less than an hour! Before, it would take multiple days if not weeks to get it done =)

Version 2.1.1 has hit the Asset Store. This version fixes smaller bugs and introduces several custom PlayMaker actions (thanks to Alex Chouls from Hutong Games for a developer copy). I don't know if these actions are useful at all, please let me know what you are trying to do and whether you need more or other actions.

V 2.1.1

Fixes Changes

• hoMove: fixed Pause() so it actually does pause the tween correctly
• hoMove: fixed bug on “closePath” not playing a walk animation while moving
• MessageExample.cs: added methods for pausing a tween with messages
• HOTween: updated to version 1.1.333, big thanks to Daniele who fixed the constrained rotation using “lockAxis” and improved “lookAhead” rotation, also optimized partial tweens and made them more garbage collector friendly ​

could we get and "every frame" option on the get path action.... I'm trying to change paths but to the same index of the other path...

Click to expand...

So you want that your object moves e.g. to the third waypoint of the new path and continues there? That would be easier with iMove, but nearly uneffective with hoMove as it always generates the whole path at start.

In iTween, there's only the possibility to change the speed once, not over time. This was discussed back on page 2. Changing the speed of an animation is described here and here, unfortunately there is no built-in method at this time.

As for HOTween, you can use its timescale property for changing its playback speed.

I don't know how to effectively convert this to unityscript, but you can add this to hoMove.cs and call it via SendMessage() or, if the scripts are located in the Standard Assets folder, get the component via unityscript and directly call the method. Hope that helps!