Search Unity

Simple Waypoint System (SWS) - Move objects along paths

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

  1. wheelbarrow

    wheelbarrow

    Joined:
    Sep 12, 2011
    Posts:
    177
    Hi Baroni, I have a simple question for you : If I have an npc following a very simple path, and at the last waypoint it enters a trigger that destroys/removes it ( GameObject.Destroy(gameObject) ), will it? I ask because I'm having a problem getting rid of a grunt that is on a non-looping path, but he won't disappear :) Was wondering if SWS has anything to do with it. Thanks for your time, and a great product.
     
  2. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,262
    Hey wheelbarrow,

    SWS doesn't disable Unity functionality :) Maybe you want to check if your object calls the OnTriggerEnter function correctly. (does it have a collider and a rigidbody attached and actually "collides" with something?)

    If the object should despawn exactly at the last waypoint, you can also set up a very simple script and trigger it through waypoint messages (see the documentation).

    Thanks!
     
  3. sicga123

    sicga123

    Joined:
    Jan 26, 2011
    Posts:
    782
    Hi

    Just a simple query really. Is it possible to set up a grid of waypoints in such a way that depending on a button press an object could move forward, back, left or right from any waypoint in the grid which had waypoints in four directions around it? Could it be done by swapping from one path to another?
     
  4. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,262
    Hi sicga,

    you won't need a waypoint system for grid movement. It's easier if you specify a movement tween once (using Unity's Lerp method, animation libraries such as iTween or HOTween) and then manipulate the target position (x,z) based on user input. So when a user pressed the "left" key, you let the object move to the current position minus a value on the x-axis. When a user presses the "forward" key, you calculate the current position plus a value on the z-axis. Hope you get the idea :)

    That should work well if every step has the same distance. If the grid doesn't have a unique size between waypoints, you can also place empty gameobjects around your map, attach a collider to them and raycast in the moving direction to detect where the waypoint is located.
     
  5. sicga123

    sicga123

    Joined:
    Jan 26, 2011
    Posts:
    782
    @Baroni Yes I figured that out. Trying to make a system set up for something else do things it wasn't ever needed for bit silly.. Already set the grid system up. I appreciate you answering so quickly and giving me the pointers. Thanks.
     
    Last edited: Feb 4, 2013
  6. ZJP

    ZJP

    Joined:
    Jan 22, 2010
    Posts:
    2,649
    HI,

    This seems like a good and cheap product. Can you make a summary of what can be done in run-time?
     
  7. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,262
    Hey ZJP,

    thank you, please find below a quick summary of the runtime mechanics:

    Easy, example provided:
    -start, pause, stop. reset movement of an animated object
    -change speed of animated object
    -change its path
    -instantiate walker object (and path) and assign a path to walk on
    -set up messages to call at waypoints

    That's basically it for the movement part, all of these things are either stated in the documentation or present in a sample scene. Since animated objects are using a predefined tween, you can't reposition waypoints while walking on the path, that would have no impact. Setting up a new path at runtime (not instantiating a path prefab) is possible and requires a bit of coding - I'm not going to far here, but you would have to create new gameobjects as waypoints, then assign a PathManager component to them and add this path to the path directory. If you have any further questions, please let me know.
     
  8. ZJP

    ZJP

    Joined:
    Jan 22, 2010
    Posts:
    2,649
    Thx.
    On my "buy-before-the-end-of-the-month" list ;)
     
  9. Hrvatss

    Hrvatss

    Joined:
    Oct 26, 2012
    Posts:
    9
    I probably didn't read well the description on the Plugin, but I have a question.

    Does this plugin support camera movement? I want to put several points in a flat surface, then when the player scores a goal, the camera moves to another random point, and also the point where the prefab is initialized, later the player scores another goal and the camera and initial point where the prefab appears moves along.

    Is that possible with this plugin?
     
  10. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,262
    Hey Hrvatss,

    thank you for your interest.

    SWS uses iTween and HOTween as animation librarys, which can animate gameobjects - since a camera is only a gameobject in the scene, camera movement is supported. I don't know if I get you right, but random point movement is integrated too. You can also choose a random path through code and then follow it till the end or pause at specific positions, align the camera and move further. This should be everything you need?

    Regards,
    Baroni
     
  11. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,697
    Hi there,
    I am wondering with your pathing system, is it very similar to iTween's Path Editor? Also, do your paths allow for the velocity of an object traversing the path to be affected by node separation distance? The further apart, the quicker the speed? Finally, is this system more effecient than iTween? Building for mobile.

    Thanks!
     
    Last edited: Feb 13, 2013
  12. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,262
    Hi renman,

    thank you for stopping by, I saw your brain on the forums before :)

    iTween's Path Editor has a few restrictions when it comes to waypoint based movement. You can create a path just fine, I think that's what it's made for, but that's basically it. As you can see on the (high resolution) pictures on the Asset Store, our path editor lets you place objects directly onto a surface in the editor. Waypoints are gameobjects, not just an array with positions. There are a few more options, such as removing or adding a waypoint in the middle of the path.

    The movement on these paths is based on either iTween or HOTween. HOTween is more powerful than iTween in terms of performance and lets you use curved paths. Again, both movement scripts do have a few options to play with - orient to path, lock rotation axis, move to path and so on. Also, there are some easetypes available: E.g. linear speed, easeIn, easeOut etc. all based on time or speed. In my implementation, the time value of HOTween is based on the whole path, so I guess a different speed between nodes isn't possible at the moment. Hope I gave you a quick overview!
     
  13. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,697
    Ok,
    What I am looking to do is to "scrub" a path, meaning, I want to be able to touch drag my camera, along the path. So the user can control the movement on the path. Is this possible? Make it go along the path in either direction. If the user removes his input, finger touch in my case, the camera (object on path) stops movement.
     
  14. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,262
    You won't need a waypoint system for this behavior. You can set up a path using HOTween, detect where the finger touch is located (on the camera) and then manipulate the progress value on the path (0 = starting point, 1 = ending point) based on the direction the user moves his finger (e.g. to the next waypoint). A waypoint system scripted mainly for automated movement wouldn't help you in this case... but I'm available for private additions to SWS of course, please PM me if you're interested.
     
  15. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,697
    Thank you.

    :))
     
  16. Rashaga

    Rashaga

    Joined:
    Feb 15, 2013
    Posts:
    2
    Hi, here's my question:
    I have a tunnel, the entrance is the A point, and the exit is the B point.
    I want to make my character (that I don't control, he was shot from a cannon and he's just flying in the scene, only guided by physics effects) move from this A point to the B point. Is it possible to attach the character to the SWS only when the character touches the tunnel entrance (A point) and detach when he leaves the tunnel (B point)?
    And, what if the player rotate the tunnel game object, making the B point be the first point to be
    touched by the character, can I make SWS make the inverse course (B to A)?
    Thanks.
     
  17. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,262
    Hi Rashaga,

    you can trigger the movement of SWS at any time through code and let the character be affected by physics the rest of the time. You could set up a trigger at the entrance, start the movement and move til the end (A to B), then take over with physics at the end of the tunnel. For B to A, it would be easier to set up an additional path than to use the old one inverted.
     
  18. Rashaga

    Rashaga

    Joined:
    Feb 15, 2013
    Posts:
    2
    Thank you, it will save me a lot of effort. I tried many different ways, believe me ;)
    Oh yeah, I forgot to mention: the tunnel will have a curve. Is that a problem when setting up new paths? I mean, my character will be able to follow the paths inside the tunnels without passing through it walls, no matter what position and rotation the tunnel was placed?
    Thanks again!
     
  19. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,262
    You only have to place the waypoints where you want them to be, no further problems :)
     
  20. NeedNap

    NeedNap

    Joined:
    Nov 1, 2012
    Posts:
    22
    Hi, this library looks great!

    I have a question: can I "snap" an object on path calling an SWS function and passing the gameobject position as argument?

    My scenario is:
    I have a rigidbody sphere that responds to AddForce method. In my scene I have a terrain with a road and an spline path used to get the "waypoints" and the camera track. When the sphere stops, I need to set his position to the nearest point on the spline path.

    Can I do that using this library?

    Thanks
     
  21. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,262
    Hi NeedNap,

    thank you for your interest.

    By default you can start at the first waypoint of the path, or at a desired waypoint after little code modifications. Getting the nearest point (anywhere on the path) and starting there isn't built in. That's basically a combination of starting at a specific waypoint and fast-forwarding to a specific time/progress. You would have to write some code to rebuild the path segment the sphere is currently in, get the approximate path position and manipulate my movement scripts. So overall no, not without scripting, sorry.
     
  22. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,422
    Hey there,

    your plugin looks really cool. I wanted to know: is there any Playmaker-Support?
     
  23. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,262
    Hey Mayhem,

    most of the methods are usable via Playmaker's SendMessage functionality. Besides, three actions are included:

    -Get Path Node: Returns the waypoint gameObject of a specific path at the defined index
    -Set Path Node: Sets the waypoint gameObject of a specific path at the defined index
    -Set Path: Changes the path of a walker object and immediately starts moving on the new path

    I think you won't need them in most cases though.

    Greetings
     
  24. EmeralLotus

    EmeralLotus

    Joined:
    Aug 10, 2012
    Posts:
    1,462
  25. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,262
    Hey rocki,

    I made a statement regarding this few pages back, here:

    http://forum.unity3d.com/threads/11...WS)-RELEASED?p=1127403&viewfull=1#post1127403

    As a summary - HOTween and LeanTween are identical when it comes to performance, but HOTween is more battle-tested. I didn't take a closer look at LeanTween, so I can only suggest you to use the waypoint array of the PathManager component as a base and create a new movement script with all that fancy LeanTween stuff in it :)
     
  26. EmeralLotus

    EmeralLotus

    Joined:
    Aug 10, 2012
    Posts:
    1,462
    Baroni, thanks for tip.

    I have the following use case, perhaps you can help out with tips on how to set it up in SWS.

    1. A comet is attached to a rotating planet.
    2. the comet goes from point A to point B on a path of 5 units. It has to traverse the path in 10 ms.
    3. The path's length changes to 10 units. The comet has to traverse this path in 10 ms.

    Note: both the path length and time to traverse the path are variable.

    Many thanks.
     
  27. Ebkac

    Ebkac

    Joined:
    Feb 3, 2012
    Posts:
    62
    I am using your product to spawn enemies and travel down a set path. My question though is after I destroy the enemy, what is the proper way to remove/destroy the path that it was traveling on?

    I am using javascript.

    Thanks for your help.
     
  28. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,262
    By saying a path of 5 units, do you mean the path has 5 waypoints and the path rotates along with the planet? In the example scene "Example_Curved", there's a sphere attached to a rotating path which does the same. Either way, I think this could work out:

    1. If the path should rotate along with the planet, parent the path to the planet gameobject. Also parent the comet, holding the hoMove component, to the planet gameobject.
    2. Start the comet's movement with the pre-defined settings: "Local" checked, "Time Value" = time and so on.
    3. That's a tricky one. Same question, by 10 units, do you mean now the path has 10 waypoints? You won't get around custom code though. You could set up a second path with the length of 10 units and start movement on this one, but if the path length is variable, this would result in a separate path for each length. So the best (and most complicated) solution would be to reposition the waypoints of the old path via code to fit the new length.

    If you want to change the speed from 10 ms to something else, change the "speed" variable of hoMove (while not moving) or use ChangeSpeed(time) (while moving). Hope this helps a bit.
     
  29. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,262
    Hi Ebkac,

    you can access and destroy paths via the WaypointManager dictionary (should work in unityscript too):

    Code (csharp):
    1.  
    2.  Destroy(WaypointManager.Paths["MyPathNameToDestroy"].gameObject);
    3.  WaypointManager.Paths.Remove("MyPathNameToDestroy");
    4.  
    Before destroying the enemy, you could also convert the path object of iMove/hoMove to a string - the path name - and then destroy that with the code above.
     
  30. MD_Reptile

    MD_Reptile

    Joined:
    Jan 19, 2012
    Posts:
    2,664
    I'm wondering if there is a simple way to get an objects position, and determine the closest point on a (curved) path to that objects position. Any suggestions that would save on testing that out? Ps always having problems creating new paths, always must use prefabs then edit them, rather than creating all new paths in the latest unity.

    Oh btw I tried "ourHoMove.currentPoint" but this seems to only tell you what number of waypoint you have reached...I need to know a very specific point. like a float as in 1.123 (in between first and second waypoint or something) which has the minimum distance to the object.

    I guess one way would be to make a new measure system for the path, then with that giving a float instead of ints, use that to compare distance to a object, until you find the closest point... I had hoped there might be a simpler way to do it with SWS though!
     
    Last edited: Mar 7, 2013
  31. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,262
    Similiar question on the same page: http://forum.unity3d.com/threads/11...WS)-RELEASED?p=1176064&viewfull=1#post1176064

    You can get the objects position on a path by using HOTween's tween.GetPointOnPath(float t) method. As for the closest point, I don't have a working solution I could share with you. Just for your information, you can also get the progress on the current segment (between two waypoints) via

    Code (csharp):
    1. if(tween != null)
    2.     Debug.Log(tween.fullElapsed / tween.fullDuration)
    Hope this helps in building your measure system - No simpler way, unfortunately.

    What exact issues do you encounter? How can I reproduce them?
     
  32. MD_Reptile

    MD_Reptile

    Joined:
    Jan 19, 2012
    Posts:
    2,664
    The problem i seem to get in most projects (even a blank project when I tried yesterday), where i go to create the waypoint manager, then name a new path, and then when I'm (alt) clicking in scene, i am unable to create any new way points. Holding alt, then clicking around just does nothing. I always use a prefab of one of the paths from the sample scenes, and edit that existing path. I could have some setting or something messed up in my editor...who knows. Would be nice though to just click through some new paths :/
     
  33. outtoplay

    outtoplay

    Joined:
    Apr 29, 2009
    Posts:
    741
    Is it possible to assign several objects to a path? Or even better, several pools of objects?

    I'd like to send some 2D sprites along a path, but random sprite from a group at random times. I thought I could assign the 'waves' and the random timing within the pools, then simply feed objects to the path. Did that make any sense?
     
  34. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,262
    Do you use a background object with a collider attached to it? A simple cube would work for testing purposes. The WaypointManager raycasts against objects in your scene to locate the ground, so you will need some colliders.
     
  35. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,262
    You can assign as much objects to a path as you like, every object will use its own tween for movement on the path.

    That's exactly how SWS works: The path is a gameobject, which contains all waypoints. The moving objects on the path, 2D sprites in your case, are separate objects with their own movement script. You'll have to set up a prefab for every sprite, then call their SetPath() method once they're spawned.
     
  36. MD_Reptile

    MD_Reptile

    Joined:
    Jan 19, 2012
    Posts:
    2,664
    There are Colliders, and even on a blank scene, spawning a plane, then trying on it won't work for me all the time, it did work once when i first purchased but not for several tries since... Maybe like i said, i could have screwed something up in my editor lol
     
  37. dsjunnesson

    dsjunnesson

    Joined:
    Dec 3, 2012
    Posts:
    15
    Does anyone have a good tutorial to how the Message system works? I want to trigger an external script once my gameobject has reach the last waypoint.
     
  38. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,262
    Now, I'm clueless :confused:

    Should be pretty straightforward to use and there's an example in the scene "Example_Straight", if you take a look at the gameobject "Capsule4". I copy-paste the image of the first post here:



    Basically you attach your own script (MessageExample.cs in this scene) containing the method you want to call, to the walker object (Capsule4), then click on "Show Message Settings". Every waypoint of the path will now have one message slot. You can add or remove slots by clicking on + and -. Locate the waypoint which should start your method and type in the name of the method. If you also select a type, e.g. "Text", the method must have a string parameter and so on. :)

    You can call an external script, that is not attached to the walker object, by calling a script with a reference to it.
     
  39. Ebkac

    Ebkac

    Joined:
    Feb 3, 2012
    Posts:
    62
    My goal is to have about a dozen or so paths on my level and assign each enemy to a random path. I can do this via a long IF statement using a random number and do an if == etc. This requires me to create a nested if == for every path though. Which is OK, if that is the only way to do it but I am hoping to streamline it so I only have one nested if.

    Currently I have two empty game objects that hold my transforms that are where my paths are generated at startup. Once they are generated I can assign enemies, send commands to them etc. So all of that is working fine for me.

    My code to spawn the enemies looks like this. My pain point is "walkeriM1.SetPath(WaypointManager.Paths[newPath1.name]);" as I cannot seem to use an array value in there. The code where I generate my paths and put them in an array is first. I have tried a bunch of different ways to formating the array value but I can't seem to get it to use it in any context. indexValue4 is what I would like to pass into it but I'm open to anything that would simplify my code.

    Thanks for any advice or suggestions on how to accomplish this.

    Code (csharp):
    1. function GenerateSWSPaths()
    2. {
    3.     if(newPath1 == null)
    4.     {
    5.         newPath1 = Instantiate(pathPrefab1, pathTransform1.position, pathTransform1.rotation);
    6.         WaypointManager.AddPath(newPath1);
    7.         arr[0] = newPath1;
    8.         arr.length++;
    9.     }
    10.    
    11.     if(newPath2 == null)
    12.     {
    13.         newPath2 = Instantiate(pathPrefab2, pathTransform2.position, pathTransform2.rotation);
    14.         WaypointManager.AddPath(newPath2);
    15.         arr[1] = newPath2;
    16.     }
    17.     print(arr[0]);
    18.     print(arr[1]);
    19. }
    20.  
    21.  
    22. function SpawnEnemy1()
    23. {
    24.     var indexValue1 : int;
    25.     indexValue1 = Random.Range(0,allEnemyAirShips.length);
    26.    
    27.     var indexValue2 : int;
    28.     indexValue2 = Random.Range(0,enemySpawnAirPoints.length);
    29.    
    30.     var indexValue3 : int;
    31.     indexValue3 = Random.Range(0,100);
    32.    
    33.     var indexValue4 : int;
    34.     indexValue4 = Random.Range(0,arr.length);
    35.    
    36.     var indexValue5 : int;
    37.     indexValue5 = Random.Range(5,25);
    38.        
    39.     var newAirEnemy : GameObject = Instantiate(allEnemyAirShips[indexValue1], enemySpawnAirPoints[indexValue2].position, enemySpawnAirPoints[indexValue2].rotation);
    40.     newAirEnemy.name = newAirEnemy.name + System.DateTime.Now.TimeOfDay;
    41.    
    42.     if (indexValue3 >= 25)
    43.     {
    44.         if (indexValue4 == 0)
    45.         {
    46.             var walkeriM1 : hoMove;
    47.             walkeriM1 = newAirEnemy.GetComponent(hoMove);
    48.             walkeriM1.speed = indexValue5;
    49.             walkeriM1.SetPath(WaypointManager.Paths[newPath1.name]);
    50.             walkeriM1.enabled = true;
    51.         }
    52.        
    53.         if (indexValue4 == 1)
    54.         {
    55.             var walkeriM3 : hoMove;
    56.             walkeriM3 = newAirEnemy.GetComponent(hoMove);
    57.             walkeriM3.speed = indexValue5;
    58.             walkeriM3.SetPath(WaypointManager.Paths[newPath2.name]);
    59.             walkeriM3.enabled = true;
    60.         }
    61.     }
    62.    
    63.     enemyCount++;
    64.     lastSpawnTime = Time.time;
    65. }
     
  40. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,262
    If I get this right, you could use loops to accomplish a more generic version. Something along these lines:

    Code (csharp):
    1. function GenerateSWSPaths()
    2. {
    3.     for(int i = 0; i < pathPrefabs.length; i++)
    4.     {
    5.          if(pathPrefabs[i] == null)
    6.             continue;
    7.          
    8.          paths[i] = Instantiate(pathPrefabs[i], pathTransforms[i].position, pathTransforms[i].rotation);
    9.          WaypointManager.AddPath(paths[i]);
    10.      }
    11. }
    12.  
    13. function SpawnEnemy1()
    14. {
    15.      //your random range stuff here
    16.      
    17.      //don't know what this does, but the new code goes in here
    18.      if (indexValue3 >= 25)
    19.     {
    20.            var walkeriM : hoMove;
    21.  
    22.            walkeriM = newAirEnemy.GetComponent(hoMove);
    23.  
    24.            walkeriM.speed = indexValue5;
    25.  
    26.            walkeriM.SetPath(WaypointManager.Paths[paths[indexValue4].name]);
    27.  
    28.            walkeriM.enabled = true;
    29.       }
    30.    
    31.    //other stuff
    32.  
    33. }
    You create an array for all your objects, so that would be for pathPrefabs, (instantiated) paths and pathTransforms. In SpawnEnemy1() I simply access the path name at the index equal to indexValue4. As you've always used indexValue4 = 0 = first path, indexValue4 = 1 = second path, this should work fine!
     
  41. subone

    subone

    Joined:
    Feb 27, 2013
    Posts:
    26
    Hello,

    I applied Ho Move Script to a car and attached to it the waypoint I created. Now the problem is that the car is moving in opposite, as if its engine is in the back and not in the front.

    What can be the problem ? I checked "Orient To Path" but still it moves oppositely.
     
  42. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,262
    Hi subone,

    seems like the car has the wrong rotation (internally). You could rotate the car in your modelling application, or if that's not an option, parent it to another gameobject with a rotation of (0,0,0), but rotate the car gameobject 180 degrees.
     
  43. llolslim

    llolslim

    Joined:
    Dec 14, 2012
    Posts:
    5
    Hi Baroni,
    firstly, I would like to say thank you for SWS, I am completely new to Unity, and this package (combined with Quill18's create series on youtube) has inspired me to get going on a range of games I have always wanted to create. As soon as I saw your video, I bought it!

    EDIT: I see my mistake: I was trying to call an array item which didn't exist on line 24. That will teach me to not take breaks when debugging. I'll leave the issue anyway, incase anyone else does something similar, unless mods would prefer me to delete it completely?...

    Anyway, on with my question/problem.

    I want to collate a number of paths into an array using tags (eventually "level1", "level2" etc) and then I will assign the player object to one of those paths depending on a number of factors. For simplicity and to learn, however, I currently am using a single path.
    My problem is, when the player is instantiated, it should in theory start moving along the path, but I get the following error
    Code (csharp):
    1. NullReferenceException: Object reference not set to an instance of an object
    2. playerMovement.Start () (at Assets/Scripts/playerMovement.cs:24)
    The "guiButtons" script is attached to an empty GameObject (and I have set both the pathPrefab and playerPrefab targets), and the "playerMovement" script and a HoMove script attached to prefabPlayer - who is instantiated via guiButtons.

    I have a Waypoint Manager object, and the path set as a prefab (not attached to my Waypoint Manager object if that makes a difference)

    I think that's everything, so here's the two scripts:
    guiButtons (C#)
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class guiButtons : MonoBehaviour {
    5.    
    6.     public GameObject pathPrefab;
    7.     public GameObject playerPrefab;
    8.     private GameObject path;
    9.     private GameObject player;
    10.    
    11. void OnGUI() {
    12.     genPaths();
    13.     genPlayer();
    14.     }
    15.    
    16. void genPaths() {
    17.     if (GUI.Button(new Rect(10, 60, 130, 25), "Make Path")) {
    18.         if (!path) {
    19.             path = (GameObject) Instantiate(pathPrefab, transform.position, transform.rotation);
    20.             path.name = "path@" + System.DateTime.Now.TimeOfDay;
    21.             path.tag = "path";
    22.             }
    23.         }
    24.     }
    25. void genPlayer() {
    26.     if (GUI.Button(new Rect(10, 85, 130, 25), "Make Player")) {
    27.         if (!player) {
    28.             player = (GameObject) Instantiate(playerPrefab, transform.position, transform.rotation);
    29.             player.name = "player@" + System.DateTime.Now.TimeOfDay;
    30.         }
    31.     }      
    32. }
    33.    
    34.    
    35.    
    36. }
    37.  
    Player Movement (c#)
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class playerMovement : MonoBehaviour {
    5.        
    6.     private int countPaths = 0;
    7.     private hoMove playerHM;
    8.     private GameObject[] pathCollection = new GameObject[10];
    9.    
    10.     void Start () {
    11.         playerHM = gameObject.GetComponent<hoMove>();
    12.         foreach(GameObject foundPath in GameObject.FindGameObjectsWithTag("path")){
    13.            
    14.             //add foundPath to array
    15.             pathCollection[countPaths] = foundPath;
    16.            
    17.             //submit foundPath to Waypoint Manager Dictionary
    18.             WaypointManager.AddPath(foundPath);        
    19.            
    20.             Debug.Log("got one (" + countPaths + "): " + foundPath.name);
    21.             countPaths++;
    22.         }
    23.         if (countPaths > 0) {
    24.             playerHM.SetPath(WaypointManager.Paths[pathCollection[countPaths].name]);
    25.         }
    26.     }
    27. }
    28.  
    29.  
    I hope it all makes sense, I have been staring at it for hours and can't see my mistake. Something obvious probably!
    Thanks and apologies for the wall of text
     
    Last edited: Mar 12, 2013
  44. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,262
    Hi llolslim,

    quickly checked your issue. As you've found out already, this would work just fine (with one path):

    Code (csharp):
    1. playerHM.SetPath(WaypointManager.Paths[pathCollection[countPaths-1].name]);
    Thank you so much for your kind words! Really happy to help you in creating your games, in some way, and I'm glad to have you aboard :)
     
  45. llolslim

    llolslim

    Joined:
    Dec 14, 2012
    Posts:
    5
    You're most welcome. Honestly, SWS meant the difference between being able to (try and) make a game and not. It was so much to take in without it, I had given up. Once I found SWS, I knew I could do it.

    If I may.. I do have another question.. I am looking to have two paths, running pretty much next to each other, and I would like the player to be able to move between the two paths. So say for example, the player 32% along pathOne, and hit "jump", they would then move to pathTwo, starting at 32%. I am sure the code is available in the example script "UserInput.cs" but I can't quite get my head around it.

    Is there a "built in" variable that tracks progession along the path or is that something that needs to be done manually? EDIT: I'm using HoMove by the way because I cannot work out how/if iTween does curved paths?
    thanks again
     
    Last edited: Mar 13, 2013
  46. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,262
    Yeah sure, keep the questions coming :) Actually your requirement is quite difficult to accomplish in SWS. You could use the currentPoint variable (see the next answer) to find the latest waypoint, then find the progress on the segment with the code below. Now you know where the object should start on path2. For moving the player there, you create another tween from the current position on path1 to the new, calculated vector position on path2. Then start the movement and fast forward to the desired progress on the segment by using tween.GoTo(float time). Also, in this case you have to make sure to only use the waypoints you need (starting from the latest waypoint passed on path1), otherwise your object would start from the beginning again.

    As I said... quite complicated. I can script something up for you over the weekend if you wish to?

    In hoMove, "currentPoint" indicates the waypoint index the gameobject has passed. For each segment (between two waypoints), you can calculate the progress on the segment by using
    Code (csharp):
    1. tween.fullElapsed / tween.fullDuration
    Example: On the half way to waypoint 3, currentPoint would be 1 (waypoint 2) and tween.fullElapsed divided by tween.fullDuration would be 0.5.
    iTween does not support curved paths out of the box, thus UserInput.cs won't help you here. There's a visual editor for iTween with curved paths, but I don't think it's that useful.
     
  47. llolslim

    llolslim

    Joined:
    Dec 14, 2012
    Posts:
    5
    Typical me!
    I wonder if this is partly my lack of knowledge when it comes to terminology, but how would I create another tween and use tween.GoTo(float time)? (See my code for what I have accomplished so far)
    If you have time, that would be amazing! I can't quite grasp it myself.

    I am more than happy to send you my complete file/work in progress if this would make it more clear for you, but here is what I have so far. The player object grabs the available paths, randomly selects one, calcluates how many waypoints there are, which two it is between and provides an accurate enough position between those two points.

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class playerMovement : MonoBehaviour {
    5.        
    6.     private int countPaths = 0;
    7.     private hoMove playerHM;
    8.     private GameObject[] pathCollection = new GameObject[10]; //Set maximum available paths to 10
    9.     private int choosePath;
    10.    
    11.     public float speed = 10f;    //speed value
    12.     private Transform[] waypointsArray; //waypoint array of path container
    13.     public int currentPoint = 0;    //current waypoint index
    14.     private Transform[] currentPath = new Transform[2]; //current path (always between 2 waypoints)
    15.     public float progress = 0f;    //object progress between those two waypoints
    16.     private float avgSpeed;    //adjusted speed variable based on path distance
    17.     private float distance = 0f; //distance from vehicle to next waypoint
    18.     private bool moving = false; //set when the vehicle is moving / stopped
    19.     private int waypointCount = 0; //number of waypoints in chosen path
    20.    
    21.     public float sizeToAdd = 1f;     //custom object size which gets added to y position
    22.    
    23.     void Start () {
    24.         playerHM = gameObject.GetComponent<hoMove>();
    25.         foreach(GameObject foundPath in GameObject.FindGameObjectsWithTag("path")){
    26.            
    27.             //add foundPath to array
    28.             pathCollection[countPaths] = foundPath;
    29.            
    30.             //submit foundPath to Waypoint Manager Dictionary
    31.             WaypointManager.AddPath(foundPath);        
    32.             Debug.Log("got one (" + countPaths + "): " + foundPath.name);
    33.             countPaths++;
    34.         }
    35.         if (countPaths > 0) {
    36.            
    37.             //randomly choose a path and set it as the active path
    38.             choosePath = Random.Range(0,countPaths);
    39.             Debug.Log("I choose path " + choosePath);
    40.             playerHM.SetPath(WaypointManager.Paths[pathCollection[choosePath].name]);
    41.             moving = true;
    42.        
    43.             //get defined waypoint array of PathManager
    44.             waypointsArray = WaypointManager.Paths[pathCollection[choosePath].name].waypoints;
    45.            
    46.             //count the number or waypoints in the chosen path
    47.             foreach(Transform oneWaypoint in waypointsArray) {
    48.                 waypointCount++;   
    49.             }
    50.            
    51.             //waypointStart and waypointFinish are included in the count
    52.             //but are not actual waypoints
    53.             waypointCount -= 2;
    54.            
    55.             Debug.Log("number of waypoints: " + waypointCount);
    56.             //store the current and next waypoint position to initialize the path between those two points
    57.             currentPath[0] = waypointsArray[currentPoint];
    58.             currentPath[1] = waypointsArray[currentPoint + 1];
    59.             //get adjusted speed based on variable speed and path length,
    60.             //so the speed stays the same at different waypoint distances
    61.             avgSpeed = speed / Vector3.Distance(currentPath[0].position, currentPath[1].position) * 100;
    62.         }
    63.        
    64.        
    65.     }
    66.     void Update() {
    67.         if (moving) {
    68.             distance = Vector3.Distance(currentPath[1].position, gameObject.transform.position);
    69.             progress += Time.deltaTime * avgSpeed;
    70.             Debug.Log("distance: " + distance + " currentPoint: " + currentPoint + " of " + waypointCount);
    71.            
    72.         }
    73.         if (distance < 0.1) {
    74.             Debug.LogWarning("got " + currentPoint + ", on to " + currentPoint + 1);
    75.  
    76.             // if next waypoint is not the last in the path and
    77.             //is not that last point
    78.             if (currentPoint < waypointCount) {
    79.                 currentPoint++;
    80.             } else {
    81.                 //vehicle has completed the loop (met the last in the path) and needs to target first waypoint again
    82.                 currentPoint = 0;
    83.             }
    84.             currentPath[0] = waypointsArray[currentPoint];
    85.             currentPath[1] = waypointsArray[currentPoint + 1];
    86.         }
    87.    
    88.     }
    89.    
    90. }
    91.  
    92.  
     
    Last edited: Mar 14, 2013
  48. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,262
    Thanks, I'll look into it and let you know :)
     
  49. Parallel_

    Parallel_

    Joined:
    Dec 9, 2012
    Posts:
    90
    Hi Baroni

    I'm using Playmaker, and not too handy with code. I'm trying to set up a player who can either choose one path or the other (both curved hoMove's) depending on get key. Also I'd like the paths to travel around with the player as there should also be ordinary free movement available so the player at any moment can choose to do the path movements . My problem is nothing happens if I set path or activate 'on start' via set property. Any tips, do I have to do a send message and get dirty with code?
     
  50. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,262
    Hi O'parallel,

    In hoMove, 'on start' only starts when the object gets instantiated, you can't activate it afterwards. You can use the PlayMaker actions included in the package. In the project panel, they are located under SWS > Scripts > PlayMaker. There is an action that directly sets the path of a target gameobject, if a path name or path object is provided - this action is called SetPath and simply uses hoMove's SetPath() method internally. Otherwise, you could also assign the path manually and only call hoMove's StartMove() method via PlayMaker's SendMessage.