Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Simple Waypoint System (SWS) - Move objects along paths

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

  1. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585
    Hi thanks for making this useful asset!
    I'm running into a visual problem regarding the line renderer,
    How can i make it look visually as smooth as my bezier path? I tried making the "spacing" smaller but it makes no difference.

    Do i have to make more Waypoints for the line renderer to be smoother? I sure hope not cause that makes things more tedious, can't it be possible to use the bezier curve data to make the line renderer smoother somehow?

    or did i just miss a value setting somewhere in inspector?

    Thanks! linequestion.PNG
     
  2. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585
    omg im sorry actually the line spacing DOES work, i was just confused for a sec cause line renderer has a funny thing where normally once i exit play mode the rendered line dissapears, but if i copy the "line renderer" component and "paste component values" back into it after exiting play mode, the line gets drawn again in the scene view!

    this is really helpful because i can edit the visual values like color and width without having to enter play mode again, BUT the spacing is on the "path renderer" script and i didn't realize it wont rerender the line with new spacing until going into play mode again.

    Looks much better!

    BUT i have another question please, is there any sort of antialising that can be applied to the line renderer just to make it as professional looking as possible, the little jaggies are really bothering me lol
    Maybe theres a URP postprocess effect that can soften the jaggies?
    Actually im planning to use the bloom postprocess effect to give everything a neon like glow which would probably mask the aliasing, but im just wondering if there an antialiasing effect that can be applied directly to the line renderer?

    thanks!

    linequestion.PNG
     
  3. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585
    I have a suggestion regarding the path detail for brazier curves.
    In the example path above , between waypoints 1 and 2 it makes sense to have lots of detail cause it’s a curve, and between waypoints 0 and 1 it makes sense to have no detail because it’s a straight line.

    so I went to show detail settings and adjusted 0-1 to be low and 1-2 to be higher, but here’s the problem!

    once my object moves across waypoint 1, there’s a noticeable snap, and vice versa as well!

    so what I really need is more detail right before and right after waypoint 1, not all the way from waypoint 0 to 1.

    could this be a feature request please?

    for now I have no choice but set higher detail for straight lines too.
     
  4. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585
    I also have a question regarding optimization,
    Let’s say I want to make 50 levels, and each level has a few paths.
    I see that the way to create paths requires a “waypoint manager” as a parent to the path child objects.

    so would it be recommended to have a separate waypoint manager for each level with a few paths or to have all the paths for all the levels parented to one waypoint manager?

    I assume if I unparent a path from the manager then either it breaks something or I can’t edit the path anymore.

    I was thinking of having a main Game scene, and to put my levels as additive scenes that contain a waypoint manager and paths for that particular level,

    then I could just additively load “level” scenes and it’ll load in the paths I need for that particular level, and I can unload the current level paths and free up memory.
     
  5. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,060
    Thanks for using Simple Waypoint System! I am glad that you figured out the "issue" with the PathRenderer component already :)

    Actually I do not know, sorry - since the LineRenderer is a standard Unity component, you might want to ask in the Graphics or URP sections.

    This is a very specific feature request, basically sections for the segment detail? However, couldn't it be worked around by placing a waypoint at the position where you want it to start having a higher detail, so a bit before waypoint 1? Either way, the dots on waypoint segments are not game objects, just Vector3 positions, meaning the performance impact is very, very low (only affecting memory, if noticeable at all). There is nothing wrong with increasing the segment detail a bit if you are not satisfied with the precision.

    Definitely the first one - there is no need to e.g. have hundreds of paths in a scene if you are not using all of them. Note that if you are re-using paths across levels, you can also make a prefab of them, or the full WaypointManager including its paths.

    This is not the case. The WaypointManager exists for creating new paths and as a path directory for quick access. Sometimes you would even want to unparent a path, for example if the path is moving with an object (imagine a tour path on a big spaceship flying around).

    Correct, that's the way you would do it. Besides being able to prefab a path as mentioned before, you are also able to create them at runtime in case of a dynamic environment - just mentioning this, in case you need it at some point.
     
    luniac likes this.
  6. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585

    Oh yeaaaa I didn’t realize I could just place another waypoint before the waypoint where I need more detail, and just make higher detail in that small segment too
    Thanks.

    good to know about unparenting still working, that’s good.

    I’ll try out the additive scenes approach, but out of curiosity, how much memory does a bezier path with say 10 waypoints take?
    I wonder if I could have like 50 paths in memory at one time on mobile.
     
  7. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,060
    I don't think someone has tested this before. A bezier path has 2 additional game objects per waypoint, so the total is waypoint count * 3. However I know of customers with around 200 paths in a mobile scene. The impact is not only caused by the game objects itself, but also in combination with all the LineRenderers and how many of them are visible at the same time. My guess is that you will not really see a big difference between 100 or 200 paths.
     
    luniac likes this.
  8. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585
    gotcha thanks!
    I have discovered something strange, the beziers in the example scene have free moving blue handles, but if i make one myself the blue handles are always opposite each other?

    is this a bug?

     
  9. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585
    May have discovered another weird thing, when i enable "closed" loop on the splinemove component, calling Reverse() method results in a jumpy reversal
     
  10. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,060
    Nope, on the BezierPathManager there is a "Connect Handles" checkbox which controls this.

    Thanks for the video, good catch. I guess this happens because on a closed loop path, the internal path is actually modified by adding one additional waypoint. You can see the difference when enabling DOTween gizmos and path drawing (a white line showing the calculated path at runtime). Going to check for the next update!
     
  11. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585
    I totally missed the connect handles checkbox lol

    And yea the extra waypoint makes sense.
     
  12. xxluky

    xxluky

    Joined:
    Dec 4, 2014
    Posts:
    16
    Hi, great asset I love it but I have a terrain trying to move animals around it. As long as I try I cannot figure out how to lock the Z axes only. Please take a look at the screenshot for a better understanding:
    Pic 1: Expected state but why is the animal rotating on the Z axes as well? Is it because of the terrain or the waypoint with a wrong rotation?
    Pic 2: set to lock X axes but it also locks Z axes, why? I think this is a bug
    Pic 3: if set to lock Z axes it does not lock the Z. Is this a bug?
    Pic 4: by setting up to lock the X asex I can get the desired rotation on the Z but not on the X
    Pic 5: Animal rotating up to the hill but not standing up

    How can I chieve to lock only the Z?
     

    Attached Files:

    • 1.png
      1.png
      File size:
      2.1 MB
      Views:
      40
    • 2.png
      2.png
      File size:
      1.9 MB
      Views:
      42
    • 3.png
      3.png
      File size:
      2.1 MB
      Views:
      44
    • 4.png
      4.png
      File size:
      2.2 MB
      Views:
      40
    • 5.png
      5.png
      File size:
      2.2 MB
      Views:
      34
  13. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,060
    Hi @xxluky, thanks for posting here with the screenshots!

    I think the confusion comes because the "Lock Rotation" dropdown is not a Vector3 value, but a Quaternion. You can see this with the dropdown also having a "W" value, which is only used by Quaternions. In a Quaternion, rotating one specific axis not only affects one value, but multiple. This is why when locking X, in "Pic 2" also Z is locked. This also the reason for "Pic 3", "Pic 4" and "Pic 5".

    But generally and the cause for "Pic 1" without locks: the underlying tween engine DOTween does not know what axis is up or down, or what kind of object you are trying to move in your game. It simply creates a tween that interpolates between waypoints and does so with the shortest way, like for a plane tilting into the next curve.

    I understand your requirement (thanks again for the screenshots) and consider re-working the "Lock Rotation" dropdown to actually lock Euler angles instead of Quaternions. For now and your use case, you will want to look into custom rotations (waypoint rotation, example scene 10) where you can exactly lay out the rotation the object should have based on each waypoint.
     
  14. power_champ

    power_champ

    Joined:
    Oct 6, 2020
    Posts:
    7

    Thanks for the response Baroni.

    The most common function I need is to find the closest point on a regular path with only 2 waypoints. I think I will do some intersection math in the meantime and wait patiently for a bezier path solution from you :p

    Thanks again for your support.
     
  15. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585
    Hi @Baroni,
    I was wondering if you could give me some advice regarding a use case im having trouble with.
    So I want to implement a dash function for an object moving along a path.

    My problem is that the distance traveled upon dashing is inconsistent.

    I tried Invoke() and coroutine approaches to say for example Invoke("DashStop", dashDuration)
    I tried in update() to increment a variable by time.Deltatime
    I tried tweening a variable for dashDuration

    I realized the problem is due to inaccuracy of using a timer or time.deltaTime in update.

    So i tried to do a dash based on distance i want traveled,
    i put this code in splineMove.cs
    return (tween.PathLength() * tween.ElapsedPercentage(false));

    and used that to determine what distance i want to travel, and checked in Update() whether the distance i want was traveled, but of course being in update() it still resulted in variable final position of object.

    I think the best solution i can think off is to simply find the Final Dash Position i want the object to reach, and just tween the object along the path to that position at some dashSpeed. Then at least the final position will be consistent gameplay wise, and any time inaccuracy won't mess up the gameplay.

    But im not sure what is a good way to explicitly tween the obj to a particular position on the path and then continue the normal path movement from that point onward?

    Can i use the existing path tween somehow or would i need to stop it and start another tween to move the obj to particular point, and then start another regular path tween from that point onward?

    But i can't figure out how to do that without a timer, is there a way to explicitly tell a tween to tween to a certain elapsedPercentage position and do a callback once it reaches that position?
    I guess i would need to create like a second mini dash tween that still tweens along the path, but its final position would be the end position of the dash and then it does OnComplete() and i could restart the main path tween at the precomputed elapsed percentage of the dash final position.

    But im really unsure how to create this tween that travels along the path only partially to the position i need, i assume it should be possible since the path data is available, maybe it could be like a fake one time waypoint or something along the path?

    or is it possible in dotween to just tween to a specific position along the tween path lol

    Any suggestions would help :)
     
    Last edited: Dec 13, 2022
  16. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,060
    Have you had a chance to look at the PathInputDemo sample scene yet? That example manipulates tween.fullPosition (percentage value on the path) based on user input; the tween is paused the whole time. You could use this approach and have your "dash" move the object to its current position + 5%, for example, using another tween that just lerps the percentage value and assigns it to tween.fullPosition. A disadvantage to this is that the distance is affected by the path length, since 5% is longer on a long path, and less on a small path.

    Another example: the RapidInput sample moves the car along the path as long as you press the 'up' arrow. The speed decelerates if you do not press the button anymore. Depending on your game requirement, I assume a dash works in the same way - accelerate fast, then decline in speed? In this example a coroutine is used that slows down the car, effectively calling splineMove.ChangeSpeed(fastValue) and then coming to a halt over the next seconds. This approach would be independent from the path length.
     
  17. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585
    the path input demo sounds useful, if I have the total path length than maybe I can calculate the relevant percentage needed for the distance so it’s the same for all paths.

    My dash is an instant stop once it’s over, no deceleration, the issue is really with using any sort of timer such as invoke, coroutine, update time.deltatime, because there is always a fluctuation to the actual timer versus duration parameter set, and this makes the dash either shorter or longer.

    if I focus on tweeting to a specific position then at least that part will stay consistent gameplay wise and it’s the important part for gameplay accuracy obviously, having an inconsistent dash final position would destroy gameplay lol
     
  18. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585
    so ive been doing lots of testing with different things and slowly maybe getting to a good solution but you said tween.fullPosition is a percentage value on the path, its not a percentage value, its just the path length divided speed on the path.

    Tweening the full position seems like the most promising way, cause i dont see any other way to tween along the path to a particular point on the path other than using fullposition variable as the tween variable.


    EDIT:
    oh i see now... in Time mode its the elapsed percentage, in Speed mode its path length / speed.

    whew... this is quite a challenge for me lol

    I definitely need to use Speed mode because besides the dash i just want my object to travel along the path at a constant speed regardless of path length.

    EDIT2:
    hmm maybe it should actually make it easier, since if im using Speed mode then the fullposition is not a percentage elapsed but a fixed value that i can calculate as pathlenght / speed.
    I dont know still gotta think it through lol my brain is fried i spent 4 hours on this.

    EDIT3:
    so seems like if keep my splineMove speed = 1 when initializing the tween, then fullPosition = Pathlength, and this applies for any path length.
    I can then immediately call ChangeSpeed() after StartMove() for example, and change to my desired object speed and the FullPosition still reflects the initialized value with speed = 1.

    So i guess that almost solves the problem from what i can see, i can just tween FullPosition to "FullPosition + dashDistance" for any path length and itll be the correct distance traveled not based on any weird ratio maths or percentages.

    The only issue is that im implementing a variable dash that can be charged, so i need to calculate the tween time duration to be say 1 second at maximum dashDistance, and .1 second at dashDistance/10, so that the speed of the dash is consistent at any distance.

    I think im getting there lol whew...
     
    Last edited: Dec 14, 2022
  19. power_champ

    power_champ

    Joined:
    Oct 6, 2020
    Posts:
    7
    I'm currently having an issue where the splineMove.ReachedEnd method is being called after I have set a new path, clearing the new tween.

    Has anyone experienced this or have any tips on how to avoid?
     
  20. jrbourne

    jrbourne

    Joined:
    May 8, 2015
    Posts:
    8
    Hello, I read on the comments on the asset store that the forum helped those of us who are completely stuck. I'm using a current version of Unity 2021.3.14f1 LTS for Mac and cannot get the simple waypoint system to work at all. When I follow the manual exactly no waypoint appears when pressing P. The error in console says "not enough waypoints to place. I'm pretty much stuck after buying last night for $15. Are any details on use that I should know about on the version of Unity I'm using? I expected to see the shadow waypoints to appear on the plane when pressing P and then moving the cursor over other places on the plane and then pressing P again.... Any help will be appreciated.

    Thanks
     
  21. lunarspore

    lunarspore

    Joined:
    Apr 14, 2022
    Posts:
    4
    Hi there! Thinking of buying this awesome asset and I had a question.

    I'm trying to make a launch star system like those seen in Mario Galaxy (example), where the player walks into a trigger, gets launched along a spline, and is dropped off at the end of the spline to continue their adventure. Would this kind of thing be easy to do with this asset?
     
  22. ml785

    ml785

    Joined:
    Dec 20, 2018
    Posts:
    107
    Hi, are there any tutorials or resources that use Simple Waypoint System for a racing style game?
     
  23. cmarfil

    cmarfil

    Joined:
    Dec 27, 2016
    Posts:
    5
    Hi! I have an issue using nav move, my agent just stops at the first waypoint, if I move the agent in playmode manually he goes back to the first waypoint, I get the feeling that the system doesn't detect that the agent has already reached the first waypoint waypoint and should go to the next one, any idea what could be happening? Thanks!
     
  24. G_EKKO

    G_EKKO

    Joined:
    Jun 29, 2018
    Posts:
    3
    Hey y'all, I've just bought this asset pack and am having an issue with trying to create everything via code. I'm creating a jenga clone and am using SWS to move blocks from the position they're at - the moment they're removed from the tower - to this drop position at the top. You can see the path actually draws successfully below at runtime:



    So the path is created successfully. The issue is that at runtime, splineMove tries to invoke this UnityEvent property called movementStart, but that property is only defined when everything is created in the editor, and not when I create these components.



    I'll break down what I'm actually doing here to lead to this issue:

    1. This is all started from within a class called BlockMover, which moves all blocks in its own attached script. First it gets all the co-ordinates needed to create the path.
    2. Then it creates the Path Manager Component - it creates 3 temporary empty Game Objects and positions them along the path, so that their respective transforms can be used for pathManager to create the paths
    upload_2023-1-9_13-28-35.png
    (Forgive the terrible code quality, its been scratched together into something which just barely works - I kinda have no idea what I'm doing but it seemingly works)
    3. The returned pathManager is used to help create the spline move component, which is attached to the block instance - the block that's moved - and then set to use the path manager.
    upload_2023-1-9_13-30-50.png

    Both components have been created and appended to the object that's going to be moved.
    4.Uh oh, null reference error (top error in console, ignore the next one :p).
    upload_2023-1-9_13-34-15.png
    The BlockMover has seemingly has created the two components and appended them to the block to be moved correctly:
    upload_2023-1-9_13-37-30.png

    So the issue is that the spline Move doesn't have the Movement Start event set. When we create these components in the editor, this UnityEvent is not null and movementStart.Invoke() has no issues.

    Can anyone explain why this UnityEvent issue is happening? Or have any examples of creating paths on runtime?
     
  25. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585
    Hi I'm having trouble with splinemove tween returning null after reaching end of current path and doing StartMove() from code to start a new movement.

    The object begins to move on StartMove() but the tween reference still returns null, how is this possible?

    Since i can't figure out how to reference the new splinemove tween, i can't control anything directly with FullPosition variable anymore.

    Any advice?

    EDIT:
    ok so i went to the CreateTween() method in splinemove.cs and directly referenced the created tween there and now i can access it, but if i try to access the tween through SplineMoveObj.tween it returns null...

    I'm assuming this is a Dotween thing but that is crazy confusing lol

    Is this a bug? cause in CreateTween() its clearly written " tween = transform.DOLocalPath", so the "tween" variable is definitely set to a new active tween. How is it possible that accessing the variable still returns the old null tween.

    if this isn't a bug, how do i reference the tween the same way as before using splinemoveObj.tween?
     
    Last edited: Jan 10, 2023
  26. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,060
    Very sorry for missing the posts here, again! I did not receive email notifications. This happened a few weeks ago too and it is making me crazy :mad:

    ---

    Ah that's right, I was referring to using <a percentage value> * move.tween.Duration() and assigning that to move.tween.fullPosition.

    That can be used as well, yes, even with a variable dash distance this should be a consistent fullPosition + dashTime assignment.

    A tween is killed and cleared on finish or when calling Stop() on the movement script explicitly. While a tween is running, the tween should definitely be assigned to that variable. Could you please post a code example that does not result in the expected behavior when trying in one of the example scenes? Thanks!

    @power_champ Does this happen when calling SetPath() on the movement script, or are you assigning the new path differently? Do you expect the method to run once and not on the new path on finish or how exactly does the issue occur?

    @jrbourne Hi! This seems to be an issue mostly in upgraded or existing projects which I have not been able to reproduce so far. Did you try to reset your editor layout as described on the FAQ? This helped other users in the past.

    @lunarspore Absolutely! "Launching to a spline" would just be starting movement on a path at any time during runtime, with either disabling or removing the movement script at the end.

    @ml785 Hi! Could you please elaborate in what direction that would go? For example an endless racing game, using Simple Waypoint System for AI cars or for the player car?

    @cmarfil Hello there! You would need to look at the stopping distance variable on the NavMeshAgent component. This should not be set to 0 as then it tries to move to the target position with 100% precision. A value of 0.5 to 1 should fit most use cases.
     
  27. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,060
    Hey @G_EKKO, thanks for your purchase and the detailed explanation with screenshots!

    There is an example included for the creation of paths at runtime: Example7_Runtime. It shows multiple use cases - instantiation a path prefab, Walker object, then letting the walker move on a path and creating a path from scratch using waypoint positions. However, the way you are doing it is fine!

    I would just suggest not setting "onStart" on the movement script since that tries to initialize the tween potentially before you have set the other properties. So that should be:
    - block.gameObject.AddComponent<splineMove>()
    - set properties and set path (except onStart)
    - splineMove.StartMove()

    The UnityEvent is a public field that should initialize itself... I have not heard of it being null after adding the splineMove component at runtime, but will try to reproduce this later today!

    Edit: thanks for the report, I was able to reproduce! In code, the events need to be initialized at the variable declaration to fix this. So in splineMove, at movementStart and movementEnd (line 171, 187) it is missing "= new UnityEvent();", and in line 179 it is missing "= new WaypointEvent();". Will be added to the next update!
     
    Last edited: Jan 10, 2023
  28. G_EKKO

    G_EKKO

    Joined:
    Jun 29, 2018
    Posts:
    3

    Oh god thankyou, you're a lifesaver. Funnily enough I found my own fix to the problem which was to create that event myself elsewhere but I'd MUCH rather use your fix since its your code and you know it far better.
     
    Baroni likes this.
  29. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,060
    @G_EKKO sure, setting the pathMode = Ignore on the movement script will ignore any path directions.
     
    Last edited: Jan 11, 2023
  30. G_EKKO

    G_EKKO

    Joined:
    Jun 29, 2018
    Posts:
    3
    Thanks - I deleted my question because I saw that my question is an FAQ but your solution did it! One thing though - it seems to be Pathmode.Ignore now instead of Pathmode.None.

    Thanks! :)
     
  31. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,060
    I answered it out of the head, thanks for correcting me :)
     
  32. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585
    Ok so do this to replicate.
    add this code to splineMove script
    public void TEST()
    {
    SetPath(pathContainer);
    }
    private void Update()
    {
    Debug.Log(tween);
    }

    in SWS example 1 scene delete all walkers except the first one and add TEST() to MovementEnd() event.

    You will see on the first loop the tween exists, but after that it returns null even while obj is tweening along the path.

     
  33. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585
    Also ive been testing GoToWaypoint and on bezier paths this doesn't move the obj to the right location, i assume this is limitation of bezier paths?

    EDIT:
    ahhhh lol i see it moves it to a point of the PathDetail, interesting lol maybe its possible to calculate the exact value needed based on waypointcount and pathdetail.



    Im trying to have full control over my obj path tween, because i want to create as much flexibility as possible such as:
    1) go from end of a path to beginning of another path
    2) go backwards into the begging of a path and into the end of the previous path
    3) if there is no path after the end of current path, go in reverse

    Since i also want the dash tween to continue its process from one path into another, i need to do this by calculating how much of the dash elapsed along the remaining path length of a path, and continue the reminder of dash along the next path.

    But for now im just trying to figure out how to simply start a new tween to go in reverse on the same path after MovementEnd() event is called.
    I don't want to rely on loop setting since itll just complicate things for when i want to switch paths and do dashing functionality.


    EDIT2:
    ok made some progress

    Code (CSharp):
    1.  public void MovementEnd(GameObject obj)
    2.     {
    3.  
    4.  
    5.         if (nextPath == thePlayer.pathContainer)
    6.         {
    7.             Debug.Log("NEXT PATH IS CURRENT PATH");
    8.             if (!thePlayer.reverse)//IF TWEEN COMPLETE AT PATH END, Start new tween from end to beginning
    9.             {
    10.                 thePlayer.startPoint = thePlayer.waypoints.Length - 1;
    11.                 thePlayer.reverse = true;
    12.                 thePlayer.SetPath(nextPath);
    13.             }
    14.             else
    15.             {
    16.                 thePlayer.startPoint = 0;
    17.                 thePlayer.reverse = false;
    18.                 thePlayer.SetPath(nextPath);
    19.             }
    at first i was trying to just call SetPath, then changing FullPosition, then calling Reverse(), but now i understand that if i just change directly startPoint to the end of the path, and set reverse flag to true BEFORE i call SetPath, then itll initiate the tween from the end of the path and MovementEnd event will be called at the "beginning" of the path which is exactly what i want.

    progress! lots of work left though lol, gotta make sure i can transition to other paths smoothly, and then the dashing functionality, but im hopeful ill figure this out lol
     
    Last edited: Jan 12, 2023
  34. cmarfil

    cmarfil

    Joined:
    Dec 27, 2016
    Posts:
    5
    @Baroni Yes, I already thought about that and I have tried many different values for the stopping distance with the same result, any other idea? thank you!
     
  35. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,060
    @luniac Interesting, thanks for the repro steps and video! Going to investigate today and will post the result here soon.

    That's true, since bezier paths have many more points, GoToWaypoint includes path points (because it is using the same array internally). This is some kind of feature, but I understand the confusion. Going to put that on my list and could try to implement an GoToWaypoint(int index, bool includePathPoints) overload where it calculates the correct waypoint internally if includePathPoints = false.

    Ugh, that's quite a complex requirement actually! Lots of math calculations involved and storing elapsed dash time between path switches. Be sure to post a link to your game when you're done :)

    Or, simpler:
    Code (CSharp):
    1.  public void MovementEnd(GameObject obj)
    2.     {
    3.         if (nextPath == thePlayer.pathContainer)
    4.         {
    5.             Debug.Log("NEXT PATH IS CURRENT PATH");
    6.             if (!thePlayer.reverse)//IF TWEEN COMPLETE AT PATH END, Start new tween from end to beginning
    7.             {
    8.                 thePlayer.startPoint = thePlayer.waypoints.Length - 1;
    9.             }
    10.            else
    11.             {
    12.                 thePlayer.startPoint = 0;
    13.             }
    14.  
    15.             thePlayer.reverse = !thePlayer.reverse;
    16.             thePlayer.SetPath(nextPath);
    17.          }
    18.      }

    @cmarfil Unfortunately I could only do wild guesses, maybe you could post a screenshot of your navMove movement script inspector, set in one of the example scenes, so I can try to reproduce the issue there? Thanks!
     
    luniac likes this.
  36. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585
    Oh yea that’s simpler lol thanks.
     
  37. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585
    Hey i was wondering is it possible to set StartPoint of a tween as a "fullposition" type value versus a specific waypoint?

    I'm thinking of a scenario where i may want to teleport object to a specific point on a different path and continue movement there.
    The only way i see right now to do this is to just set the fullposition after tween has begun but since this is kind of like fast forward in a tween, all the passed through MovementChange event callbacks get called. This isn't really a big deal if i'm not using them for gameplay purposes but just wondering if there is a cleaner way to directly control a StartPoint of tween more precisely instead of as waypoints.


    EDIT:
    Also found another weird issue.
    Lets say i have a bezier path with 5 waypoints.
    So if i do "nextPath.waypoints.Length" with nextPath being a PathManager, i get the "5"
    Only when i do SetPath(nextPath) on a tweening obj and call obj.waypoints.length, then i get complete count which includes the pathPoints, in my case it returns "40".

    The problem is if im trying to begin a movement in reverse from the end of the path, i was setting StartPoint - nextPath.waypoints.Length - 1, and of course since it returned "5" and its a bezier path, the tween began near the beginning of the path in reverse.

    So the only way i get the correct number of waypoints is to already start the tween at some arbitrary start point and then once again start the tween but this time StartPoint = obj.waypoints.length - 1 will return the correct bezier waypoint count.

    Is there no way to just get the bezier waypoint count from the start?

    EDIT2:
    NVM i found solution nextPath.GetPathPointIndex(nextPath.waypoints.Length - 1);
    didn't realize there were methods in pathmanager class to convert to bezier pathpoints.
    Setting StartPoint = 9999999 works too lol but isn't my style lol
     
    Last edited: Jan 14, 2023
  38. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585
    I'm having a weird bug when calling SplineMove.Reverse();
    As you see from the video, there are 2 paths, i begin on path 1, calling Reverse() while still on path 1 works perfectly, no bugs.
    Then i go on to path 2 which is done simply using:
    Code (CSharp):
    1. if (!isNextPathReverse)
    2.             {
    3.                 theActor.startPoint = 0;
    4.                 theActor.reverse = false;
    5.             }
    6.             else
    7.             {
    8.                 theActor.startPoint = nextPath.GetPathPointIndex(nextPath.waypoints.Length - 1); //Get Bezier StartPoint
    9.                 theActor.reverse = true;
    10.             }
    11.             theActor.SetPath(nextPath);
    But when i call Reverse() this time, well... you see what happens in the video, something under the hood is messing up the tween.
    I can see in the Reverse() method that it starts a new tween and does some other changes but its still confusing to me right now so not sure what the issue is.

    I assume its just a simple bug to fix hopefully.
    Worse comes to worst, i could technically just store FullPosition at the frame i want to reverse, and just stop current tween and start new tween on same path in reverse and set FullPosition to the stored value.

    But ill wait for you to respond to see if modifying the Reverse() method could work somehow.

     
  39. ml785

    ml785

    Joined:
    Dec 20, 2018
    Posts:
    107
    Is there a way to make a gameobject follow a path of waypoints in a more 'human' manner, so that for example they randomly weave in and out of the center-line of the path? rather than only following the center. Thanks.
     
  40. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585
    I did some more testing and i just dont understand why its bugging out.
    So if i just tween on a single path, if i Reverse() before reaching the end and calling MovementEnd(), then it works fine.
    But once MovementEnd() is called and it runs this code:
    Code (CSharp):
    1. if (nextPath == theActor.pathContainer)
    2.         {
    3.             //Debug.Log("NEXT PATH IS CURRENT PATH");
    4.             if (!theActor.reverse)//If tween completes in the forward direction, start new tween in reverse direction
    5.             {
    6.                 theActor.startPoint = theActor.waypoints.Length - 1;
    7.             }
    8.             else
    9.             {
    10.                 theActor.startPoint = 0;
    11.             }
    12.             theActor.reverse = !theActor.reverse;
    13.             theActor.StartMove();
    It just teleports the obj to the beginning or end and tweens from there, if i keep calling Reverse(), it just does all kinds of random starts from one end or the other.

    I tried writing my own Reverse script
    Code (CSharp):
    1.  public void Reverse()
    2.     {
    3.         float reverseFullPos = theActorTween.PathLength() - theActorTween.fullPosition;
    4.         if (!theActor.reverse)//If tween completes in the forward direction, start new tween in reverse direction
    5.         {
    6.             theActor.startPoint = theActor.waypoints.Length - 1;
    7.         }
    8.         else
    9.         {
    10.             theActor.startPoint = 0;
    11.         }
    12.         theActor.reverse = !theActor.reverse;
    13.         theActor.StartMove();
    14.         theActorTween.fullPosition = reverseFullPos;
    15.  
    16.     }
    And i get almost same result,
    If i call Reverse() now it works but then a second or 2 later the obj teleports to the beginning or end and starts tweening from there, i just don't understand the logic of this. Why is it happening a second or 2 after the initial Reverse()

    Im really stumped for now.
    why does it work the very first time traversing the path, but after the first time it reached MovementEnd() and the code makes it reverse, now Reverse() doesn't work right.
     
  41. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585
    My only suspicion right now is that somehow the spline tween is not destroyed before new one starts, and so 2 path tweens run at once and when the old one is finished it interrupts the new one with yet another new one that gets created on MovementEnd()

    will have to do more testing to confirm….
     
  42. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,060
    @luniac this seems to be a combination of issues when using splineMove.Reverse() and your own method which (again) sets the splineMove.reverse variable (reverse + reverse = no reverse) and modifying the startPoint. For example in your video, when moving on the second path and calling Reverse() the object starts from the end of the path. I guess this is because at that time the startPoint is set to waypoints.Length - 1 and Reverse() creates a new tween from that position, instead of the current startPoint.

    Also a note regarding the "then a second or 2 later the obj teleports", does the object reach a waypoint when teleporting? It could be that an event or the MovementEnd() method is fired which breaks the usual movement.

    Am I right to assume that you would want to call splineMove.Reverse() at any moment on the current path? Including combining paths to a loop like in your video, when not reversing it continues on the other path from that position? If so, I could throw something together to show you how I would do it.

    @ml785 This is not built-in. You can add a method for this yourself very easily though. Under the object with the movement script, add another game object. Attach a new script to this child object that manipulates the Transform.position locally or over time (update/coroutine). The result would be that the main object with the movement script is still following the path center, but the child has some arbitrary offset applied.
     
    ml785 likes this.
  43. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585
    Well im not calling both my reverse() and splinemove.reverse() at the same time lol, i just tested one or the other way.

    Ill double check the MovementEnd() callback to see if its getting called, but why would it be called while the obj is somewhere on the path, itd have to be a tween that was meant to stop but it kept tweening till the end and the event was called right?

    and yes i want full control of the obj on any path to reverse, i actually made a pretty good implementation for going from one path to another in either direction, i just have a collider on the first and last waypoints and when the obj is inside it, i know what path is ending and what path is beginning and whether it should be in reverse or forward direction.

    Getting Reverse() to stop buggin out is my main issue right now lol
     
  44. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585
    Did some testing, the splinemove.Reverse() teleport bug only calls MovementEnd() the second time it teleports, so at first when calling Reverse() it teleports immediately to the end of the path and start a new tween in reverse, then at a point when the ORIGINAL tween would have reached the end of the path, it teleports to the opposite end and MovementEnd() is called.

    I have tested this by calling Reverse() right at the end of the tween and at the beginning of the tween, if i call it right near the end then the second time it teleports and calls MovementEnd() is almost immediately, while if i do it at the beginning of the tween, it takes almost the length of the whole path to teleport the second time.

    So this proves that the when Reverse() is called, for some reason it doesn't set StartPoint() to be exactly the point the obj is when Reverse() is called, so the obj just tweens in reverse from end of the path.

    And it proves that the original tween doesn't get killed somehow because it calls MovementEnd() when it finishes even while a new tween is already running.

    My version of Reverse() is way worse, it just calls movementend() randomly and is super buggy lol, idont understand why.
     
  45. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585
    Ok heres a video, as you can see, once i call Splinemove.Reverse() function AFTER obj reaches the end of the path the first time and reverses, the a new reverse tween begins, and the current tween does not get destroyed, they are both running at the same time!
     
  46. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585
    OMFG i think i figured out the issue,
    i had to comment out tween = null here:
    Code (CSharp):
    1. switch (loopType)
    2.             {
    3.                 //none means the tween ends here
    4.                 case LoopType.none:
    5.                     //tween = null; //CUSTOM COMMENTED OUT
    6.                     return;
    7.  
    because tween = null, i guess any Stop() method call wasn't working:
    Code (CSharp):
    1. public void Stop()
    2.         {
    3.             StopAllCoroutines();
    4.             waitRoutine = null;
    5.  
    6.             if (tween != null)
    7.                 tween.Kill();
    8.             tween = null;
    9.         }
    10.  
    Since tween was already null then tween.kill() was not getting called...

    Actually funny weird thing is if i put tween.kill() before tween = null inside the Case LoopType.none, then no new tweens were able to be created on the object, StartMove() did nothing, and DotWeen manager object showed no new running tweens.

    I dont know wtf is up with this lol but i dont care, seems like simply commenting out that line "tween = null" fixed everything,

    Doing Reverse() works at any time now, i didn't even have to make my own Reverse() function.
    I'm gonna do more tests but i hope this problem is over.

    is there anything that i break by commenting out "tween = null" that im not aware of?
     
  47. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,060
    That's actually partly the desired behavior in some cases, since a few users did want to set the startPoint themselves before calling Reverse(). This should not affect the regular behavior when moving on a tween though, without using event callbacks and path switching.

    I think the issue here is that MovementEnd() is called while still on the current tween, not actually after it ended (but right on the very last update step of it), so this might not be the expected order and something I would like to change.

    I don't think so: setting tween = null there is a cleanup step for releasing memory, since on Looptype = None it would be expected that the object does not run another tween anytime soon. If it works for you, it works ;)

    Thank you very much for committing your time to this and explaining your approach, this definitely helps me to understand your use case and difficulties with the MovementEnd event, LoopType=None and Reverse() method in combination. I have put this on my to-do list for a rework and will make sure that it works "out-of-the-box" in a future update!
     
    luniac likes this.
  48. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    585
    no problem :)
    I am wondering though about releasing memory, i have DotWeen setup as AutoKill and Recycle to true, so it shouldn't matter if i don't do "tween = null" hopefully.

    Ahh i see what you mean about MovementEnd() being called on current tween, yea if its set to null then it won't be Stopped by a future StartMove()
     
    Baroni likes this.
  49. spikezart

    spikezart

    Joined:
    Oct 28, 2021
    Posts:
    65
    Hey there, I have the following errors. Ive compared to previous deployments that are fine but can't work out what the problem is yet. See attached humanoid inspector. located at waypoint 3 of route 1. Any suggestions please? Thanks.

    Parameter 'Speed' does not exist.
    UnityEngine.Animator:SetFloat (string,single)
    SWS.MoveAnimator:OnAnimatorMove () (at Assets/SWS/Scripts/Helper/MoveAnimator.cs:64)

    Parameter 'Direction' does not exist.
    UnityEngine.Animator:SetFloat (string,single,single,single)
    SWS.MoveAnimator:OnAnimatorMove () (at Assets/SWS/Scripts/Helper/MoveAnimator.cs:65)
     

    Attached Files:

  50. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,060
    Hi @spikezart, the MoveAnimator script tries to set the variables "Speed" and "Direction" on the Animator Controller. You are probably using an own controller in the Animator component which does not have these variables.
     
    spikezart likes this.