Search Unity

Simple Waypoint System (SWS) - Move objects along paths

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

  1. ikonakona

    ikonakona

    Joined:
    Jun 28, 2016
    Posts:
    4
    Thanks. I think I understand what you mean, but I do want the object to return to localY = 0 so that it can continue to walk after jumping. Is there an option for the object to maintain its XZ plane speed automatically so I can just play with the Y values during jumping?

    I have something like this which calculates the new speed of the object to maintain a XZ plane speed, but with this I'm basically defining the jump off and landing points which seems to limit how I can jump and where I can land.

    Code (CSharp):
    1. Vector3 relativePos = endJumpPosition - startJumpPosition;
    2.  
    3. //This maintains a constant speed in the XZ plane that's the same as entering the jump. Only tested when "jumping down" (endJumpPosition.y < startJumpPostion.y)
    4. speed = startSpeed / Mathf.Sin (Vector3.Angle (relativePos, Vector3.down) * Mathf.Deg2Rad);
    5. sMove.ChangeSpeed(speed);
    Would I have to do something like this every frame while in a "jumping state" to constantly change the object's speed so that its XZ plane is constant?
     
  2. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    @ikonakona I'm not sure I understand, if the timeValue on the movement script is set to linear easetype or speed, then the moving speed of the object is always constant regardless of the axis? Did you modify the easetype on timeValue 'time' before switching to 'speed' by any chance?
     
  3. ikonakona

    ikonakona

    Joined:
    Jun 28, 2016
    Posts:
    4
    Sorry, maybe a picture will help: http://imgur.com/I7QnLFe

    I'm using speed control so yes, it's maintaining its speed in 3D space. From the picture, I want x to equal the startSpeed during the jump. This means I have to change the speed of the object (now traveling at an angle) so that x is still startSpeed. This is like a projectile motion where your velocity perpendicular to gravity remains constant because gravity only acts downwards.

    I'm trying to make something generic so that I can make the character jump at any point on the path. When in the jumping state, the localY > 0 and I want it's XZ plane speed to be constant because the character will be "in the air". Once the character lands, localY = 0 and I want to switch back to walking. So in a sense the spline path is acting like a ground and I can only jump above it.

    Maybe I'm approaching this wrong. Sorry.
     
  4. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    @ikonakona
    Thanks for the picture. With linear easing, your object will traverse the section 'x' at the same speed like the rest of the path, so my last statement is still valid... I think what you're really up to is that your object should traverse the part 'x' in a specific time, not speed, right? If you would work with the path acting like a ground, what prevents you from working with a coroutine that modifies the localY value over a specific amount of time, e.g. 2 seconds, for the full jump (1 second up, 1 second down)?

    I'm on vacation right now until next week, but if still don't get this right, I would love to take a look at a project that reproduces the issue / mathematic question you are having. If you find some time, please send it to my email info [at] rebound-games [dot] com.
     
  5. ikonakona

    ikonakona

    Joined:
    Jun 28, 2016
    Posts:
    4
    Thanks for the suggestion. I see what you mean with the time. I'll experiment around a bit to see if I can change from speed to time when jumping. I like speed control little better because I am making a wave-based tower defense shooting game and I want the enemies to move at a constant speed rather than traversing a path in given time (path lengths all vary).
     
  6. IgorAherne

    IgorAherne

    Joined:
    May 15, 2013
    Posts:
    393
  7. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    Hi @IgorAherne,
    please don't use reviews to request support (there even is a hint to not use it as a support channel right before you press submit).

    You can put an object at a percentage value on a path by accessing the tween directly. This is a method provided by DOTween: tween.fullPosition (expects a time value, but you can divide by tween.Duration to get the percentage). Please have a look at our input example scene for a sample implementation.
     
    IgorAherne likes this.
  8. kumar123k

    kumar123k

    Joined:
    Jul 5, 2016
    Posts:
    25
    Hi i want to create path at run time how to make pls explain.
     
  9. kumar123k

    kumar123k

    Joined:
    Jul 5, 2016
    Posts:
    25
    to be more clear i will provide waypoints at run time it have to calculate in run time and move the charecter how to do that?
     
  10. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    There is no code example on how to do that, but it's very easy:
    - create gameobject and add the pathmanager component to it
    - create multiple gameobjects (acting as waypoints) and position them in your scene
    - assign the waypoints to the pathmanager's "waypoints" array.

    Done. Note that adding or removing waypoints at runtime while an object follows the path does not update its moving tween. You have to restart the movement on this path for waypoint changes to take affect.
     
  11. kumar123k

    kumar123k

    Joined:
    Jul 5, 2016
    Posts:
    25
    yea it was working but when i restart it was going to start position.
    i want to update the position at runtime for next waypoint without affecting the movement how to do that ?
     
  12. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    @kumar123k Please read the last part in my previous post again. Tweens are fixed animations which cannot be modified at runtime. If you want to change waypoint positions, you have to restart movement. You can also restart movement at a defined waypoint by using the startPoint variable.

    Our navMove movement script does not have this requirement as it uses pathfinding, not tweens. Also if you just want to rotate or move the full path without modifying individual waypoints, you can use local paths.
     
  13. lzt120

    lzt120

    Joined:
    Apr 13, 2010
    Posts:
    93
    Just modify the source code to fixed out of range error when using bezer path manager for navmove:

    navmove.cs:

    Code (CSharp):
    1. //get Transform array with waypoint positions
    2. waypoints = pathContainer.GetWayPoints();
    3. //Array.Copy(pathContainer.waypoints, waypoints, pathContainer.waypoints.Length);
    4.  
    PathManager.cs
    Code (CSharp):
    1.  
    2. //add this method :
    3. public virtual Transform[] GetWayPoints()
    4. {
    5. return waypoints;
    6. }
    7.  
    BezierPathManager.cs
    Code (CSharp):
    1.  
    2. public override Transform[] GetWayPoints()
    3. {
    4. List<Transform> trans = new List<Transform>();
    5. for (int i = 0; i < bPoints.Count; i++)
    6. {
    7. trans.Add(bPoints[i].wp.transform);
    8. }
    9. return trans.ToArray();
    10. }
    11.  
     
  14. lzt120

    lzt120

    Joined:
    Apr 13, 2010
    Posts:
    93
    I wonder if there is arrow draw on screen to indicate the direction of the waypoint
     
  15. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    @lzt120 May I ask for the reason why you want to use BezierPathManagers with navMove, as the intermediate points on segments are being ignored by navMove anyway?

    There is no rotation gizmo for waypoints. I've tried to draw default handles in a previous version but Unity slowed down to an unusable state when drawing more than 8 handles. You can select the waypoint gameobject to see the default handles.
     
  16. bigdoor

    bigdoor

    Joined:
    Jan 27, 2015
    Posts:
    3
    Hi,
    It's possible to instantiate different paths at runtime with SWS?
    Thanks!
     
  17. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    Hi @bigdoor,
    yes, you can both instantiate prefab paths or create them from scratch by code at runtime.
     
    bigdoor likes this.
  18. jboys65

    jboys65

    Joined:
    Aug 7, 2016
    Posts:
    3
    It's a good asset. I really like it.

    Is anyone knows how to set different speed between any two waypoint?

    ex: waypoint0 to waypoint1 ->Speed 10
    waypoint1 to waypoint2->Speed 20
     
  19. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    Hey @jboys65, you can use events on the movement script for that. Add an event in the inspector at the waypoint, drag the movement script in and let it call ChangeSpeed with your desired speed value.
     
    jboys65 likes this.
  20. jboys65

    jboys65

    Joined:
    Aug 7, 2016
    Posts:
    3
    @Baroni

    Thank you for the reply,can you tell me which event from component should I choose?

    I tried all of them, but none of them can drag the movement script in.

     
    Last edited: Aug 9, 2016
  21. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    @jboys65 please see the attached screenshots.

    EventsScreen1.png EventsScreen2.png
     
  22. jboys65

    jboys65

    Joined:
    Aug 7, 2016
    Posts:
    3
    @Baroni Thank you so much! It works!!! Any manual show this? I cna't it.
     
    Last edited: Aug 10, 2016
  23. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    I've made the screenshots specifically for you, these are not found in the manual. The manual has a description about events on page 5 though.
     
    jboys65 likes this.
  24. Mr-Logan

    Mr-Logan

    Joined:
    Apr 13, 2006
    Posts:
    455
    Can waypoints be saved into prefabs? And can the waypoints of multiple prefabs be connected during runtime?
    (Think like a multipart maze that's assembled during runtime)
     
  25. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    @Mr-Logan Paths can be saved as prefabs or created dynamically at runtime, which in most cases makes more sense if you've already got the maze logic. Connecting paths would just mean figuring out what's the next path and adding an event or calling a method with that path on the movement script, whatever fits better.
     
  26. Mr-Logan

    Mr-Logan

    Joined:
    Apr 13, 2006
    Posts:
    455
    Perfect! Thank you for the quick reply :)
     
  27. Oshigawa

    Oshigawa

    Joined:
    Jan 26, 2016
    Posts:
    362
    Hello Baroni,

    i am using sws in conjuction with playmaker, but unfortunately, due to unity's limitations (i presume) i am unable to save a prefab that will store state machine which contains set random waypoint action with predefined waypoints, like this:



    It works fine in scene, but when i save it as a prefab, all the elements are empty. Is there a way to fill elements in runtime upon instantiation?
     
  28. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    Hi @Kruko,

    scene elements can't be referenced in prefabs because prefabs are cross-scene objects by definition. That's a Unity limitation indeed. The variable storing path references in your screenshot seems to be an array/list, so you would need to get the path object in your scene and put it in there at runtime (I'm not that familiar with playmaker, please ask on their forums on how to do that part). Alternatively, save the full path gameobjects as prefabs too, because prefabs can be referenced in prefabs.
     
  29. Oshigawa

    Oshigawa

    Joined:
    Jan 26, 2016
    Posts:
    362
    Hello @Baroni,

    thanks for the answer, i'll save them as prefabs then :)
     
  30. blamejane

    blamejane

    Joined:
    Jul 8, 2013
    Posts:
    233
    Hi @Baroni

    I have been trying for hours to get my enemy to Pause on the first and last waypoints. I'm not sure whether the problem is me, or with DOTtween, or with SWS. I've tried searching this thread first but didn't find an answer to what I could be doing wrong...

    Using your runtime example #6 the pause doesn't work either. I modified it so that the walker #6 would pause when the event is called. Here's my code:

    Code (CSharp):
    1.    
    2. public void ActivateForTime(Object move)
    3.     {
    4.      
    5.         splineMove myMove = (splineMove)move as splineMove;
    6.         myMove.Pause ();
    7.         StartCoroutine(ActivateForTimeRoutine(move));
    8.         myMove.Resume ();
    9.     }
    10.  
    Here's how it's called:

    Code (CSharp):
    1.          
    2. myEvent.AddListener(delegate{receiver.ActivateForTime(example6.moveRef);});
    The above fails to pause the walker. Any ideas?
    I'm using Unity 5.3.5 and SWS v5.1.1

    Thanks,
    Valerie

    EDIT: This is a runtime instantiation of player, enemy, path, etc. Everything seems connected and events do fire, they just don't Pause the splineMove object.
     
  31. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    @blamejane Hey, you are calling both myMove.Pause() and myMove.Resume() in the same frame, so it does not have any effect. The StartCoroutine(...) between those calls does not stop the instruction from directly passing through the full method. If you know the delay beforehand, I would suggest calling myMove.Pause with the amount of seconds to wait (and removing the myMove.Resume call).
     
  32. blamejane

    blamejane

    Joined:
    Jul 8, 2013
    Posts:
    233
    Actually I've completely removed the Resume() call and it still fails to pause. I've also tried Pause(6) thinking possibly I needed to provide a length of time. Still doesn't pause. Have you tried it? I'm assuming this should work correct?

    thanks @Baroni
     
  33. blamejane

    blamejane

    Joined:
    Jul 8, 2013
    Posts:
    233
    BTW, this is example #7 Runtime, walker #6. In any case if I set it to Ping Pong, the pause will happen correctly on the last waypoint. If it's set to loop, which the example #6 is, then pause won't work.

    Edit: while switching to PingPong does seem to fix example 7, in the case of my project, even having Ping Pong path type will not cause the splineMove object to Pause() or Stop() when the event is added at runtime onto the last waypoint (delegate method is called - but Pause/Stop have no effect). Using the same runtime event add listener logic, I can get it to work if I use 2nd to last waypoint.

    Does this info help any?
     
    Last edited: Aug 24, 2016
  34. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    Thanks for the additional info @blamejane and sorry for the confusion. I've tried to get this working and found that you are correct, the last waypoint does not react to actions affecting the tween directly. This is because tweens and events happen at the same time. So when the object reaches the last waypoint, the tween gets destroyed/reinitialized and the event is being fired. The event then can't access the tween because it does not exist anymore (temporarily).

    If you need to call tween actions (such as pause) on the last waypoint as in this case, a feasible workaround would be to set the loop type to none, and have your event start a coroutine that calls StartMove() after a certain amount of delay - effectively simulating the loop type manually via code. i.e.

    Code (csharp):
    1. public IEnumerator WaitForRestart(float seconds)
    2. {
    3.      yield return new WaitForSeconds(seconds);
    4.      gameObject.GetComponent<splineMove>().StartMove();
    5. }
     
  35. blamejane

    blamejane

    Joined:
    Jul 8, 2013
    Posts:
    233
    Thanks for the workaround. I have a new problem that I hope you can help with...

    I'm trying my hand at navMesh movement, originally it was splineMove on my game object, and I'm getting navMesh array index errors after switching to the navMove script. Error:

    IndexOutOfRangeException: Array index is out of range.
    SWS.navMove+<Move>c__Iterator9.MoveNext () (at Assets/SWS/Scripts/Movement/navMove.cs:156)
    UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
    SWS.navMove:StartMove() (at Assets/SWS/Scripts/Movement/navMove.cs:141)
    SWS.navMove:Start() (at Assets/SWS/Scripts/Movement/navMove.cs:105)

    I decided to start with a fresh New project, nothing but SWS. Added a plane, a sphere, and waypoint path (bezier). Baked the nav mesh. Applied navMove script to the sphere and assigned the path. Hit play and I see the same Index out of range error.

    EDIT: Just tried the standard path and it worked fine.
     
  36. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    @blamejane bezier paths don't work with navMove because (1) pathfinding doesn't make use of any additional path detail and (2) it would only consume more resources which would not be needed.
     
  37. blamejane

    blamejane

    Joined:
    Jul 8, 2013
    Posts:
    233
    I'm trying to instantiate my path and enemy at runtime. This is a standard (smooth) path with two waypoints. The enemy has a navMove script attached. I kept getting null reference exception when calling navMove.SetPath() until I added agent = GetComponent<NavMeshAgent>(); to naveMove.cs (line 401); like so...

    Code (CSharp):
    1.        
    2.        /// <summary>
    3.         /// Disables any running movement routines.
    4.         /// <summary>
    5.         public void Stop()
    6.         {
    7.             StopAllCoroutines();
    8.  
    9.             // add this and it works...
    10.             if(agent == null)
    11.                 agent = GetComponent<NavMeshAgent>();
    12.  
    13.             if (agent.enabled)
    14.                 agent.Stop();
    15.         }
    16.  
    17.  
    This works but it's not really a solution since this will get replaced next time you update the asset. Can you tell me if possibly there's a better way to fix the null reference for agent...like a SetAgent() that I'm not aware of?

    Thanks.
     
  38. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    @blamejane this should be fixed in the latest version. Are you using 5.2? The agent reference getter has moved from Start() to Awake() there. If you are already on 5.2, could you please show how you are instantiating and accessing navMove.
     
  39. blamejane

    blamejane

    Joined:
    Jul 8, 2013
    Posts:
    233
    Thanks for the fast reply. I'm on SWS v5.1.1 but will get v5.2 and test.

    EDIT: Great timing v5.2 fixed the problem!
     
    Last edited: Aug 31, 2016
    Baroni likes this.
  40. CF-Games

    CF-Games

    Joined:
    Jun 2, 2013
    Posts:
    134
    Hello,

    I'm currently working on a mine cart moving along tracks in 2D, and everything works fine except for the part where I have a loop for one part of the tracks. The cart goes up about half way and then it rotates to stay upright instead of staying upside down. This is pretty much like a roller coaster so I want it to be able to go upside down and follow the tracks. I currently have the path mode set to Sidescroller 2D. Is there a way to make it able to go upside down during the mine track loops?

    Also, I currently have several different bezier paths set and am using SetPath() to change paths for the mine cart. Is there a way to tell when the cart reaches the end of one path so I can tell it to change paths? I realize I can set a SendMessage() event on the last waypoint, but I can only do that for the first path. After I change the path to another path using SetPath(), how can I add an event to the last waypoint of the current path? Or is there an easier way to do this?
     
  41. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    Hi @CF-Games,

    currently I'm working on a feature that allows for more fine grained control of rotations along the path. It is using the waypoint rotations you specify on the path. You can find an animated preview of that on our Twitter page. Unfortunately I have to wait for the next version of DOTween to come out, so at the moment the only solution for detailed rotation control is to disable the path mode on the movement script and use scripted rotations like multiple chained coroutines.

    For adding events to the last waypoint, you can also do this at runtime after switching to a new path. See the runtime example scene for a sample. Alternatively you could add a collider to the waypoint gameobject and let it trigger something in your script - see the events example scene for a sample on that.
     
  42. IgorAherne

    IgorAherne

    Joined:
    May 15, 2013
    Posts:
    393
    Hey Baroni, I've added a small chunk of code to rotate bezier waypoints with rotation handle. Don't know, found it easier than in screen-space

    Code (csharp):
    1.  
    2. //because the last waypoint has a control point at the waypoint origin,
    3.             //below we check against a Vector3.zero value and ignore that for the opposite
    4.             toParent.Normalize();
    5.  
    6.             //allow user to rotate, but only when close enough
    7.             if(Vector3.Magnitude(Camera.current.transform.position - point.wp.transform.position) < 32){
    8.                 point.wp.transform.rotation = Handles.RotationHandle(point.wp.transform.rotation, point.wp.transform.position);
    9.             }
    10.             toParent = point.wp.transform.rotation * (isLeft ? Vector3.forward : Vector3.back);
    11.  
    12.  
     
  43. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    Thanks for the suggestion @IgorAherne, I think you will like the new move and rotation handles which are already implemented for the next update! These are coming with an improved way of selecting individual waypoints, that should make modifying waypoint positions and rotations more convenient.
     
    IgorAherne likes this.
  44. Osteel

    Osteel

    Joined:
    Jan 17, 2014
    Posts:
    59
    Hi!

    I just purchased SWS because it does exactly what I hoped to achieve. However, following the instructions, I'm unable to place waypoints into the scene view.

    Based on the PDF instructions:

    1. Created a plane (for raycast collision detection)
    2. Added the Waypoint Manager from Window>SWS
    3. With the manager selected, named and started a new path
    4. With the cursor over the plane, press either the P or C key

    Am I missing something completely obvious? Thanks!
     
  45. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    Hi @Osteel,

    what Unity version are you using? Did you restart Unity and tried again? The instructions you have posted are correct.
     
  46. Osteel

    Osteel

    Joined:
    Jan 17, 2014
    Posts:
    59
    @Baroni, I'm currently on 5.4.0f3. I'll give it a shot on my other computer as soon as I get home.
     
  47. Osteel

    Osteel

    Joined:
    Jan 17, 2014
    Posts:
    59
    Hey, just wanted to follow up that it seems I just needed to reset. The asset is really fun and I'm enjoying tinkering around with it.

    I would like to ask, however, you opinion on how to go about achieving the following work flow. I would like to create tracks that contain curves (I suppose in a sense, it's a race track). However, I need to have extremely accurate placements of the waypoints using measurements I've defined.

    I've been manually making sure the waypoints x,y,z positions are aligned as needed and that's been fine.

    The issue I'm having is when there's a curve:

    1. Waypoints that are before and after a curve don't seem to maintain a straight line even if their points are aligned

    2. I need the agents to walking exactly as the path is outlined, without stepping off

    3. Even if I lock the rotation of the agent, it still seems to rotate on it's Z axis - especially once it's curved

    Attached is a screenshot of the waypoints issue with the curve. Thanks!
     

    Attached Files:

  48. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    @Osteel I can't see anything wrong with the curve in your screenshot, it's a perfectly smoothed out curve. Be aware that the spline curve is defined by all waypoints, not only waypoints that are placed 'curvy'. So all points are taken into account and it doesn't really matter if they are aligned on one axis. If you need more control over the curve, use bezier paths.

    2. Are you using navMove for your moving objects? This would be using pathfinding between waypoints, which naturally means that they are following the shortest route. Use splineMove for exact movement.

    3. Maybe try a different axis such as X? If you want to let it not rotate at all, set the pathMode to 'ignore'.
     
  49. Spookyy2

    Spookyy2

    Joined:
    Oct 10, 2016
    Posts:
    2
    SWS not working here also. How did you reset?
     
  50. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,267
    Quit Unity and start it again. Which version are you running?