Search Unity

Help with adding a delay in a waypoint script (UnityScript) please?

Discussion in 'Scripting' started by FusionGames, May 2, 2012.

  1. FusionGames

    FusionGames

    Guest

    Joined:
    Feb 8, 2012
    Posts:
    60
    Hi everyone,
    I created a script for my game in which the enemy character patrols the waypoints in a loop. I would like to add a delay of a second or so as he reaches each waypoint. However, for the life of me, I cannot seem to get anything to work. Here's my script...any ideas? Any and all help will be very much appreciated! :)

    Code (csharp):
    1. //AI Movement Script
    2.  
    3. //Inspector Variables
    4. var waypoint : Transform[];
    5. var speed : float = 5;
    6. var loop : boolean = true;
    7.  
    8. //Private Variables
    9. private var currentWaypoint : int;
    10.  
    11. //Game Loop
    12. function Update () {
    13.  
    14. if(currentWaypoint < waypoint.length)
    15. {
    16.         var nextWaypoint : Vector3 = waypoint[currentWaypoint].position;
    17.         var moveDirection : Vector3 = nextWaypoint - transform.position;
    18.         var velocity = rigidbody.velocity;
    19.         if (moveDirection.magnitude < 1)
    20.         {
    21.             currentWaypoint++;
    22.         }
    23.         else
    24.         {
    25.             velocity = moveDirection.normalized*speed;
    26.         }
    27. }
    28. else
    29. {
    30.     if(loop)
    31.     {
    32.     currentWaypoint = 0;
    33.     }
    34.     else
    35.     {
    36.     velocity = Vector3.zero;
    37.     }
    38. }
    39.  
    40. rigidbody.velocity = velocity;
    41. }
    42.  
     
  2. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    what you want is a state system. So lets say that your ai is supposed to travel along a waypoint system. looping, ping pong or one way, your choice. At each marker he makes a choice. Wait for a second, proceed to the next waypoint or whatever. To do this you just hold a float that keeps track of the next decision time.

    If he is currently going to a waypoint, it is set to 1 second ahead of the current time. (so it keeps advancing where you would never reach it if you never reached the waypoint) When he reaches the waypoint, it is set to the current time.

    At this point you make a decision. Wait, proceed, investigate or whatever. If you proceed, you travel to the next waypoint, using the rules above. If you wait, you then decide for how long by setting the next decision float to that much time. Thus waiting.

    Investigation and other things happen if something seems out of place or there is an enemy nearby to attack. So lets say that he found something of interest and goes to check it out. You save the search start point and then create whatever path to follow to investigate. Once the investigation is done, or enemy killed or lost, he simply plots a course back to the start point and immediately makes his choice for the next part.
     
  3. FusionGames

    FusionGames

    Guest

    Joined:
    Feb 8, 2012
    Posts:
    60
    Hmm...what you are saying makes sense...but I'm not quite sure how to implement it. Could you give an example script please? Also, I've done some more work on the script...and I think I've made some progress another way...but it's not working. Instead of stopping movement, it just stops following the waypoints and continues off in one direction. Any ideas as to what I'm doing wrong? It prints "waypoint reached" when it reaches the waypoint...so I'm definitely getting at least that part right. Now just to get it to stop moving...

    Code (csharp):
    1. var loop : boolean = true;
    2.  
    3. //Private Variables
    4. private var currentWaypoint : int;
    5. private var enemyActive : boolean;
    6.  
    7. //Game Loop
    8. function Start()
    9. {
    10.     enemy = this.gameObject;
    11.     enemyActive = true;
    12. }
    13.  
    14. function Update()
    15. {
    16.     if(enemyActive)
    17.     {
    18.         MoveEnemy();
    19.     }
    20. }
    21.  
    22. function MoveEnemy()
    23. {
    24.  
    25. if(currentWaypoint < waypoint.length)
    26. {
    27.         var nextWaypoint : Vector3 = waypoint[currentWaypoint].position;
    28.         var moveDirection : Vector3 = nextWaypoint - transform.position;
    29.         var velocity = rigidbody.velocity;
    30.        
    31.         if (moveDirection.magnitude < 1)
    32.         {
    33.             currentWaypoint++;
    34.             print ("Waypoint Reached");
    35.             enemyActive = false;
    36.         }
    37.         else
    38.         {
    39.             velocity = moveDirection.normalized*speed;
    40.         }
    41. }
    42. else
    43. {
    44.     if(loop)
    45.     {
    46.     currentWaypoint = 0;
    47.     }
    48.     else
    49.     {
    50.     velocity = Vector3.zero;
    51.     }
    52. }
    53.  
    54. rigidbody.velocity = velocity;
    55. }
    56.  
     
  4. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    im sure you could do it with a co-routine, but meh...

    Code (csharp):
    1.  
    2. var waypointPause : float = 0;
    3.  
    4. function Update()
    5. {
    6.     if(waypointPause > 0)
    7.       waypointPause -= Time.deltaTime;
    8.     else if(enemyActive)
    9.         MoveEnemy();
    10. }
    11.  
    12. function MoveEnemy()
    13. {
    14.  if(currentWaypoint < waypoint.length)
    15.  {
    16.         var nextWaypoint : Vector3 = waypoint[currentWaypoint].position;
    17.         var moveDirection : Vector3 = nextWaypoint - transform.position;
    18.         var velocity = rigidbody.velocity;
    19.  
    20.         if (moveDirection.magnitude < 1)
    21.         {
    22.             currentWaypoint++;
    23.             print ("Waypoint Reached");
    24.             enemyActive = false;
    25.             waypointPause = Random.Range(1,3);
    26.         }
    27.         else
    28.         {
    29.             velocity = moveDirection.normalized*speed;
    30.         }
    31. }
    32. else
    33. {
    34.  
    35.     if(loop)
    36.     {
    37.      currentWaypoint = 0;
    38.     }
    39.     else
    40.     {
    41.      velocity = Vector3.zero;
    42.     }
    43. }
    44. rigidbody.velocity = velocity;
    45. }
    46.  
    47.  
    48.  
     
  5. Poya

    Poya

    Joined:
    Jul 3, 2011
    Posts:
    51
    It took me a while to get used to it, but for this sort of sequenced events, Coroutines are really great. In this case, I'd think you can use a nested coroutine like this (this is just a rough pseudo code):

    Code (csharp):
    1. IEnumerator Patrol()
    2. {
    3.     foreach (var wayPoint in wayPoints)
    4.     {
    5.         yield return StartCoroutine(MoveToWayPoint(wayPoint));
    6.         yield return new WaitForSeconds(Ranom.Range(1, 3));
    7.     }
    8. }
    9.  
    10. IEnumerator MoveToWayPoint(WayPoint wayPoint)
    11. {
    12.     while (transform.position != wayPoint.position)
    13.     {
    14.          MoveABitCloser(wayPoint);
    15.          yield return null;
    16.     }
    17. }
    18.  
    Using coroutines simplifies the code a lot because you don't have to manage states so much. You just fire and forget, so to speak.
     
  6. FusionGames

    FusionGames

    Guest

    Joined:
    Feb 8, 2012
    Posts:
    60
    @ jlcnz - Thanks man! One small problem though...I implemented your changes, and changed a few things to make it work, but it doesn't actually stop the movement of the object...it just stops the object from following the waypoints. So when it reaches a waypoint, it continues on in whatever direction it was heading for whatever time I set the wait time to, and then it resumes following the waypoints. Maybe it's something to do with the way I set up the if/else statements?

    Here is the updated half-working script.

    Code (csharp):
    1. //AI Movement Script
    2.  
    3. //Inspector Variables
    4. var waypoint : Transform[];
    5. var speed : float = 5;
    6. var loop : boolean = true;
    7. var waypointPause : float = 0;
    8.  
    9. //Private Variables
    10. private var currentWaypoint : int;
    11. private var enemyActive : boolean;
    12.  
    13. //Game Loop
    14. function Start()
    15. {
    16.     enemy = this.gameObject;
    17.     enemyActive = true;
    18. }
    19.  
    20. function Update()
    21.  
    22. {
    23.  
    24.     if(waypointPause > 0)
    25.  
    26.       waypointPause -= Time.deltaTime;
    27.  
    28.     else if(enemyActive)
    29.  
    30.         MoveEnemy();
    31.  
    32. }
    33.  
    34.  
    35.  
    36. function MoveEnemy()
    37.  
    38. {
    39.  
    40.  if(currentWaypoint < waypoint.length)
    41.  
    42.  {
    43.  
    44.         var nextWaypoint : Vector3 = waypoint[currentWaypoint].position;
    45.  
    46.         var moveDirection : Vector3 = nextWaypoint - transform.position;
    47.  
    48.         var velocity = rigidbody.velocity;
    49.  
    50.  
    51.  
    52.         if (moveDirection.magnitude < 1)
    53.  
    54.         {
    55.  
    56.             currentWaypoint++;
    57.             print ("Waypoint Reached");
    58.             waypointPause = 5;
    59.  
    60.         }
    61.  
    62.         else
    63.  
    64.         {
    65.  
    66.             velocity = moveDirection.normalized*speed;
    67.  
    68.         }
    69.  
    70. }
    71.  
    72. else
    73.  
    74. {
    75.  
    76.  
    77.  
    78.     if(loop)
    79.  
    80.     {
    81.  
    82.      currentWaypoint = 0;
    83.  
    84.     }
    85.  
    86.     else
    87.  
    88.     {
    89.  
    90.      velocity = Vector3.zero;
    91.  
    92.     }
    93.  
    94. }
    95.  
    96. rigidbody.velocity = velocity;
    97.  
    98. }
     
  7. FusionGames

    FusionGames

    Guest

    Joined:
    Feb 8, 2012
    Posts:
    60
    Never mind...I figured it out :D I changed the else statement on line 42 to an if statement and added a new else statement, like this:
    Code (csharp):
    1. if(waypointPause <= 0)
    2.  
    3.         {
    4.  
    5.             velocity = moveDirection.normalized*speed;
    6.  
    7.         }
    8.        
    9.         else
    10.        
    11.         {
    12.        
    13.             velocity = Vector3.zero;
    14.        
    15.         }
    Now it works perfectly. Thank you all for your help!