Search Unity

Simple Waypoint System (SWS) - Move objects along paths

Discussion in 'Assets and Asset Store' started by Baroni, Dec 10, 2011.

  1. SIV

    SIV

    Joined:
    May 7, 2014
    Posts:
    219
    Hmm, i think it could be done using the loop for.
     
  2. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,260
    @SIV I'm not sure what exactly you are trying to do, I've just mentioned two ways - the Reverse() method which works at runtime on a running tween, or the startPoint approach which indeed tells the object to go straight to that waypoint. You can implement a combination of both things, or others from the Scripting Reference (e.g. set the "reverse" flag to true before calling StartMove() again), depending on your exact needs.
     
  3. SIV

    SIV

    Joined:
    May 7, 2014
    Posts:
    219
    Ok thank you, im gonna play with that for a bit.
     
  4. Lucideus

    Lucideus

    Joined:
    Dec 7, 2015
    Posts:
    25
    Does locking the Z-rotation work for anyone in Unity 2020.3.32f1 or similar?
    I've tried this asset, Bezier Curves, DoTween and none of them seem to be able to lock the Z-rotation properly. The only way I've found possible to actually do this is creating a separate script that forces the z-eulerangle to remain 0 otherwise it does absolutely nothing when moving along a spline.
     
  5. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,260
    Hi @Lucideus, the human walkers in the sample scenes all use Z-rotation locks to not tilt sideways. You can check this by trying to modify their Z-rotation in the inspector at runtime - it will stay at 0. This is done by setting the "Lock Rotation" dropdown to X, since in global rotation, the Z value rotates around the X axis.
     
  6. Lucideus

    Lucideus

    Joined:
    Dec 7, 2015
    Posts:
    25
    Hmm, I'm not sure I follow.

    Here is an image of my problem. The top image is when I don't run a custom script on the Model-child of the enemy ship, and I set the Lock Rotation to "X" in the Spline Move component. It doesn't face in the spline direction properly. Setting it to lock Z does nothing, though.
    To better explain it, I have enemies spawn in from a random direction, in this case from the top of the screen. Once they line up and go straight forward (towards the player) though they don't rotate upwards properly, they stay "turned" on the Z-axis.

    The bottom image is when I run my custom script that I've attached to the child instead that contains the model itself.
    Code (CSharp):
    1. public class LockRotation : MonoBehaviour
    2. {
    3.     public Transform ParentTransform;
    4.  
    5.     void Update()
    6.     {
    7.         if (ParentTransform.rotation.z != 0)
    8.             this.transform.eulerAngles = new Vector3(
    9.                 ParentTransform.rotation.eulerAngles.x,
    10.                 ParentTransform.rotation.eulerAngles.y,
    11.                 0);
    12.     }
    13. }
    That's the full code for it. That does what I want it to (bottom image). Here, once they line up they no longer stay turned on the Z axis.

    Edit: Made some gifs to clarify it a bit better perhaps:
    Spline Move Lock Z Rotation: https://imgur.com/i4OkkEQ
    Spline Move Lock X Rotation: https://imgur.com/axZXa0P
    Custom Lock (script above): https://imgur.com/Y204YR9
     
    Last edited: Jun 28, 2022
  7. Lucideus

    Lucideus

    Joined:
    Dec 7, 2015
    Posts:
    25
    As a separate question; is there a way to get the distance of a spline, or between certain waypoints along the spline? (including any curves and such) Thanks!
     
  8. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,260
    @Lucideus thanks for the gifs. Still difficult to tell, but there does not seem to be much difference between X rotation and your custom lock script, except for the beginning of the path when the objects fly down. The issue and why X rotation does not work as expected could be caused by a default rotation on the model, unexpected turns of the path (where DOTween still tries to force a path alignment), or another splineMove setting. Again, very difficult to tell based on screenshots - if you've solved by using your custom script and are happy with the result, that's fine! If not, just know that I am available to look at it directly, if you could send me a repro package via PM.

    Yes: if you only need a rough estimate on the full path length for information or further calculation, you can find it when selecting the PathManager in the inspector. The path length value is displayed in the upper part, however this does not take curves into account.
    For the exact length including curves (like it is displayed in the scene) you can call the static method WaypointManager.GetCurved instead, by passing in the path waypoints and then handing the result over to WaypointManager.GetPathLength which does the distance calculation.
     
  9. Lucideus

    Lucideus

    Joined:
    Dec 7, 2015
    Posts:
    25
    Fair enough! So far I've not run into any real issues with my solution so I'll stick to that for the time being.
    Thank you for the help (regarding the waypoint-distance also)! :)
     
  10. potter3366

    potter3366

    Joined:
    Oct 15, 2009
    Posts:
    65
    How to update the waypoints positions if I change them in runtime?
     
  11. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,260
    Please see the FAQ for this, last entry. When using splineMove, since tweens do not recalculate the full path every frame you have to restart the tween / movement for any waypoint changes to take effect i.e. by calling StartMove() again. You have the option to let the object start from its current position (moveToPath enabled) and to the next waypoint (startPoint variable) where it left off, before calling StartMove().
     
  12. potter3366

    potter3366

    Joined:
    Oct 15, 2009
    Posts:
    65
  13. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,260
    @potter3366 moveToPath is only active for the current cycle. As I wrote, you have to explicitly set it to true (again) before calling the StartMove method.

    I'm not sure what kind of visual scripting tool that is in your second screenshot.
     
  14. potter3366

    potter3366

    Joined:
    Oct 15, 2009
    Posts:
    65
    NodeCanvas
     
  15. potter3366

    potter3366

    Joined:
    Oct 15, 2009
    Posts:
    65
    Sorry Baroni, but I can't complete the task.

    1) MoveToPath is enabled
    2) The object moves between waypoints and when it is, for example, between the 2nd and 3rd points, I change y from waypoint 1 (after some time).
    3) Explicitly set moveToPath to true
    4) Calling the StartMove method

    The object does not continue from where it left off and goes back-forward and only after a short time he continues properly. Maybe I have to change the position of the waypoint exactly at the time when the object is at that waypoint?
    How will I know exactly when the object is at a certain waypoint?
     
  16. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,260
    Hi @potter3366, I created a quick script that works as expected, if I understood you correctly.

    The script:
    Code (csharp):
    1. using UnityEngine;
    2. using SWS;
    3.  
    4. public class MoveBackTest : MonoBehaviour
    5. {
    6.     private splineMove move;
    7.  
    8.     void Start()
    9.     {
    10.         move = GetComponent<splineMove>();
    11.     }
    12.  
    13.     public void MoveBack(int index)
    14.     {
    15.         if (index != 3) return;
    16.  
    17.         move.startPoint = 1;
    18.         move.moveToPath = true;
    19.         move.StartMove();
    20.     }
    21. }
    22.  
    The setup:
    I used scene Example1_Splines and the first Walker object. I attached the MoveBackTest script from above and added it to its waypoint events. This event is fired at each waypoint, that's why we check for waypoint 3 in code. If the object reaches waypoint 3, it will move to waypoint 1, basically creating an endless loop between waypoints 1-3 unless you would deactivate the script.

    upload_2022-7-11_12-10-48.png

    I'm not quite sure what "goes back-forward and only after a short time he continues properly" means exactly, but answering this question, you can use waypoint events for this.
     
  17. Tinniman

    Tinniman

    Joined:
    Dec 14, 2020
    Posts:
    49
    Hi, and thanks for making this nice additions to Unity! I would love the simple waypoint system to work in my game but I think I have tried everything there is. My game is built on URP and I cannot place waypoints. After the place waypoints turns yellow nothing happens when I push (P) or any other button for that matter. Is there a conflict with URP?
     
  18. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,260
    Hi @Tinniman, thanks for posting here. Did you try to reset your layout (top right corner)? I was unable to reproduce yet, however I have heard reports that resetting the editor layout fixes the placement issue, most of the time for projects that were upgraded between Unity versions. URP should not have any effect on the placement - it just requires a box collider to detect surfaces. If the issue still persists, could you send me a tiny project that reproduces this via private message? Thank you!
     
  19. Tinniman

    Tinniman

    Joined:
    Dec 14, 2020
    Posts:
    49
    Hi Baroni and thanks for the insanely quick response! Yes, you are right. Resetting layout made me place waypoints. Great, let´s see how this plugin works on my project! (maybe you should add this info to the docu:)
     
  20. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,260
    It already is - first point on the FAQ ;)
     
  21. Tinniman

    Tinniman

    Joined:
    Dec 14, 2020
    Posts:
    49
    Oops. Not in the PDF I read included.
     
  22. QueenLegit

    QueenLegit

    Joined:
    Jun 10, 2020
    Posts:
    5
    Hi. @Baroni, I actually purchased this asset at about 2018 but I lost access to that account. This is a new one.
    So I'm creating a navigation system with about 50 buildings and a drop-down menu to select which building I want my player to go. When I click on a drop-down option, my player goes there as I want it to. However, I used the easyroads3d asset to create a road network and I want the player to only get to any of those buildings using the road network and I want to use your waypoint system to achieve this. My problem is, how do I go about it? How do I make my player know which Waypoint path is the shortest to follow to get to each of these buildings.
    Please bear in mind that I will have to create a lot of waypoints because there are several buildings in my scene and several road networks as well
     
  23. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,260
    Hi there, unfortunately I am not familiar with easyroads3d and its "road network" system so I am only able to give general advice on what you would like to achieve below.

    You have access to all paths in the WaypointManager's "Paths" dictionary. Generally, for detecting which path is the shortest, in a first step you would either have to find out which waypoints and paths are near your player - that would save a bit of performance by avoiding to loop over all paths. Then, loop over the remaining paths and sum up the distance between waypoints so you can pick the shortest distance and path.

    I understand that this might still cause a hit in performance with several or hundreds of paths. Regardless of which other asset you are using, keep in mind that you can also create a path at runtime. So instead of creating hundreds of paths and finding one, it could make more sense to write an independent logic to detect the shortest way and then place waypoints along that route.
     
  24. AssetTest

    AssetTest

    Joined:
    Mar 20, 2018
    Posts:
    4
    HI, when I use the Bezier Path Manager the spline move does not trigger the Movement change event. Only Movement start and movement end are triggered. It is not working in my own setup but also not in your examples, in which I changed the path to the bezier path. Can you please check that?
    I need to know at which waypoint I am on the bezier path. Thank you.

    Edit: Some additional information:
    I did further testing and found out that the Movement change is triggered on bezier paths that are created with the Way point manager. I create my own path during runtime and in this case only start and end are triggered.

    This is how I generate the points.
    The last lines are where the component is added and I believed "Create" would create all the important data for it to work based on the waypoints that I use.

    Code (CSharp):
    1. GameObject container = new GameObject();
    2.             container.name = "BezierWaypointContainer";
    3.             Vector3[] tilePositions = FloorTileGenerator.Instance.GetFloorTilePositions();
    4.             if (tilePositions.Length > 0)
    5.             {
    6.                 int waypointIndex = 0;
    7.                 for (int i = 0; i < indexList.Length; i++)
    8.                 {
    9.                     Vector3 lookDir = Vector3.zero;
    10.                     int dir = -1;
    11.                     if (i > 0 && i < indexList.Length - 1)
    12.                     {
    13.                         lookDir = GetLookDirection(tilePositions[indexList[i - 1]], tilePositions[indexList[i]], tilePositions[indexList[i + 1]]);
    14.                         //Debug.Log("Look direction for vector " + i + " with magnitude of " + lookDir.magnitude);
    15.                         if (IsLeft(tilePositions[indexList[i]] - tilePositions[indexList[i - 1]], tilePositions[indexList[i + 1]] - tilePositions[indexList[i - 1]]))
    16.                         {
    17.                             dir = 1;
    18.                         }
    19.                     }
    20.                     GameObject waypoint = GameObject.Instantiate(bezierWaypointTemplate);
    21.                     waypoint.transform.position = tilePositions[indexList[i]];
    22.                     waypoint.transform.rotation = Quaternion.LookRotation(lookDir * dir);
    23.                     waypoint.name = waypointIndex.ToString();
    24.                     waypoint.transform.parent = container.transform;
    25.                     waypointIndex++;
    26.                 }
    27.             }
    28.             container.AddComponent<BezierPathManager>().Create();
    29.             forkliftSplineMove.pathContainer = container.GetComponent<BezierPathManager>();
    30.             forkliftSplineMove.StartMove();
    31.             return container;
    32.         }

    Edit2: I changed the bezier path to the normal path manager using the exact same code as shown above and the movement change event is triggered. I guess there must be a bug somewhere for the bezier path. It does not trigger movement change event when the path is created during runtime.
     
    Last edited: Sep 13, 2022
  25. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,260
    Hi @AssetTest!
    Code (CSharp):
    1. container.AddComponent<BezierPathManager>().Create();
    That method takes an array of Transforms to use as waypoints, you would not be able to call it without passing in the array - as long as you did not modify it.

    Additionally, a bezier path consists of two control points per waypoint, which further define the path. You can see these control points when creating a path manually, where there is one control point placed on each side of the waypoint. The Create(...) method accesses them by looking for GetChild(0) and GetChild(1) of the waypoint, however in your code I could not see that you are creating them.

    So ultimately, the waypoint change events not firing would be caused by the path not being defined correctly and actually not having any intermediate waypoints assigned at all.
     
  26. mysoulkavi500

    mysoulkavi500

    Joined:
    Sep 14, 2022
    Posts:
    1
    please share live chat OR contact details on priority basis. I need urgent basis. I am getting error :Billing is not available."
     
  27. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,260
  28. gvela13

    gvela13

    Joined:
    Jul 5, 2018
    Posts:
    3
    just purchased this from the asset store because I thought it was really what I needed (still do) but when trying to import the package into my unity project, it's not importing everything and scripts throw error messages, it does not let me select everything to import x( I'm using Unity 2020.3
     
  29. gvela13

    gvela13

    Joined:
    Jul 5, 2018
    Posts:
    3
    upload_2022-10-17_21-35-13.png
    getting the following errors:
     
  30. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,260
    Hello @gvela13, thank you for posting here.

    The errors you are seeing are coming from the DOTween plugin, trying to access its "Outline" class but failing to do so. This is likely to be a namespace clashing issue. When making use of scripts from other sources (assets) it is best practice and usually an absolute must have to either give classes a unique name or put them into their own namespace. For example, all of your own scripts should go into a "YourProject" namespace.

    Do you have a class named "Outline" in your project that does not have its own namespace?
     
  31. spikezart

    spikezart

    Joined:
    Oct 28, 2021
    Posts:
    72
    Hey all, Navmesh Ping Pong example looks like the best fit for what I want to do but I don't see any instructions for it.
    I've copied the components and scripts across to my scene but I'm still not getting it to work.

    Does anyone have a link to a guide ?

    Thanks :)
     
  32. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,260
    Hi @spikezart! There are no instructions because this is all set on the navMove component in the inspector: specifically you would look at the loop type dropdown which contains the ping pong option.

    Could you explain what does not work?
     
    spikezart likes this.
  33. LukiSouki

    LukiSouki

    Joined:
    May 21, 2021
    Posts:
    5
    Hello, i recently bought your asset, this is exactly the thing i was looking for!

    There is just 1 thing i can't figure out: i want to initiate different events at different waypoints but i can't figure out how to target the waypoints when i set up the event in the Spline move component. I can set an event when the path is starting and one when the path ended, but for the events that should trigger on waypoints i can't select at which waypoint.
    I think i just missed something.
     
  34. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,260
    Hi @LukiSouki, thanks for your purchase! Besides the start+end events, there is also a change event, delivering the current waypoint index that was reached. Based on this index, you can specify the action that should be done at each waypoint.

    The example scene "Example5_Events" contains a sample for this:

    upload_2022-10-19_10-22-46.png

    upload_2022-10-19_10-23-30.png

    Instead of setting this up in the inspector, you can also just have your own script subscribe to the movement script's movementChangeEvent.
     
    LukiSouki likes this.
  35. spikezart

    spikezart

    Joined:
    Oct 28, 2021
    Posts:
    72
    Hey, I'd like to slow down the animation speed of the walk animation in MoveController but the animation's inspector is blanked out. Is there any way I can change the speed another way, or better still, change the animation speed for each animated object just like I can change the movement speed for each? Thanks
     
    Last edited: Oct 26, 2022
  36. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,260
    Hi @spikezart, the animation speed is controlled globally in the Animator. I do not know your exact requirements, but usually this value is set to something that matches the actual animation so it does not produce e.g. any foot sliding or otherwise looks off.

    upload_2022-10-26_10-32-16.png

    If you would like to have an individual speed per object, you could introduce a public variable to the MoveAnimator script and then add it as a multiplier. It is used at the end of the script, so it would look like this:
    Code (CSharp):
    1. animator.SetFloat("Speed", speed * multiplier);
     
    spikezart likes this.
  37. spikezart

    spikezart

    Joined:
    Oct 28, 2021
    Posts:
    72
    I'd like to slow down the animation itself either for all, and create duplicates for different animated characters, or somehow a per character variable. I'd then match the movement speed in the nav mesh agent to ensure there is no foot drag.

    If I add that below the last two variables I get:
    "Assets/SWS/Scripts/Helper/MoveAnimator.cs(66,48): error CS0103: The name 'multiplier' does not exist in the current context"

    Also, the inspector for each animation in the controller are hidden so I can't access the variables as you've shown above. Im running 2020.3.31f1 if that makes a difference.
    Thanks
     
  38. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,260
    It was an example, did you add a "public float multiplier" variable at the top?

    Not quite sure what you mean. The screenshot I posted is when double clicking the controller in the project folder, then selecting an animation - nothing else or special. I'm using 2020.3 too.
     
  39. spikezart

    spikezart

    Joined:
    Oct 28, 2021
    Posts:
    72
    ah.. double click, thanks. Im still not seeing the global speed option as you've illustrated but for now I'll park this to focus on my MVP.
    Thank you for your support as always Baroni.
     
    Baroni likes this.
  40. SickaGames1

    SickaGames1

    Joined:
    Jan 15, 2018
    Posts:
    1,270
    Can this asset move a ship on a water plane?
     
  41. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,260
    You are welcome, and thank you very much for the positive asset review!

    On all mostly flat undergrounds, yes. You could even simulate waves by modifying the transform position locally up/down, while the object is moving on the path.
     
    spikezart likes this.
  42. SickaGames1

    SickaGames1

    Joined:
    Jan 15, 2018
    Posts:
    1,270
    Yeah. I was just wondering if I put it on Gaia water, if it will run without issue in a loop.
     
  43. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,260
    Unfortunately I am not familiar with how Gaia water is different than a regular flat water plane. In the end, it would not really matter though as the object moves wherever you put the waypoints. Be it in a cave, on water or in the air (any 3d position).
     
    SickaGames1 likes this.
  44. spikezart

    spikezart

    Joined:
    Oct 28, 2021
    Posts:
    72
    Hi Baroni, is there any way to sharpen up the corners of the routes? I have pedestrians I want to try to maintain a route along foot paths and would like them to turn sharper, or is it a case of adding waypoints to create a 90 degree curve for example?
    Thanks
     
  45. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,260
    Hi @spikezart, for the standard path there is no additional setting that influences corner shapes - you would indeed need to place more waypoints to achieve the desired result. On a bezier path you have more options to sharpen corners using the extra control points.

    If only individual moving objects should be affected rather than modifying the path, you could also try the waypoint rotation feature (see sample scene).
     
    spikezart likes this.
  46. spikezart

    spikezart

    Joined:
    Oct 28, 2021
    Posts:
    72
    Got it. Thanks
     
  47. power_champ

    power_champ

    Joined:
    Oct 6, 2020
    Posts:
    10
    Hi Baroni,

    Have been using this for a while now with great success. The need has arisen to find the closest point on a path from a given position. Have seen some comments around it but have yet to find a solution.

    Any tips?

    PC
     
  48. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,260
    Hi @power_champ! That's a good question, which I would be happy to implement - but have not done so yet, because of the different needs from different users.

    I guess you have seen this before: currently one possible way would be to loop over the waypoints of a path and do a Vector3.Distance check, storing the nearest waypoint and returning its index at the end. Obviously there is a major downside to this: only waypoints are considered, not sections between them. When using bezier paths, you also have the possibility to loop over individual path points (displayed with yellow dots on the path segments in the editor), so this is more precise, but requires more CPU time due to potentially hundreds of path points.

    I can think of a solution that would work for both path types, however the disadvantage would be that it requires simulating another tween "ghost" object that moves along the path in big steps per segment, and comparing the smallest distance per segment to ultimately return the lowest one. Maybe this will ship in an experimental method in one of the next updates - for now, the Vector3.Distance check could be used instead.

    The difficulty in getting this right, is that there is no way to actually save performance by doing a pre-calculation for both waypoints or segments. For example the middle of a segment could be close to point, but a later waypoint could be closer than the surrounding waypoints. Doing a waypoint check first would fail this in case. Or, a point on a later segment could be closer than a previous one - taking the first segment and saving on looping over the others would again be wrong.
     
    Last edited: Nov 20, 2022
  49. Inventis_kr

    Inventis_kr

    Joined:
    Oct 24, 2019
    Posts:
    5
    I can't find that turn on gizmo for enabling add path via scene view.

    You need to add it the FAQ.

    If gizmos is disabled in the scene view, i can't add the way point because OnSceneGUI is not called.

    thank you.
     
  50. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,260
    Click the Gizmos button:
    upload_2022-11-21_17-50-10.png

    Additionally, SWS components should be enabled within the Gizmos list:
    upload_2022-11-21_17-50-37.png