Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Question problem with assigning agent destination using scripts

Discussion in 'Scripting' started by Trussmister, May 15, 2024.

  1. Trussmister

    Trussmister

    Joined:
    Mar 24, 2024
    Posts:
    24
    hi im trying to make an ai patrol an area and if it spots the player it follows, but it chases the player no matter its sight range, code attached below, thanks.
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using Unity.AI.Navigation;
    4. using UnityEngine;
    5. using UnityEngine.AI;
    6.  
    7. public class EnemyLogic : MonoBehaviour
    8. {
    9.     public GameObject Player;
    10.     NavMeshAgent agent;
    11.     public Transform[] waypoints;
    12.     void Start()
    13.     {
    14.         int childnum = 0;
    15.         agent = gameObject.GetComponent<NavMeshAgent>();
    16.         foreach (Transform child in GameObject.Find("Waypoints").transform)
    17.         {
    18.             childnum++;
    19.         }
    20.         waypoints = new Transform[childnum];
    21.         childnum = 0;
    22.         foreach (Transform child in GameObject.Find("Waypoints").transform)
    23.         {
    24.             waypoints[childnum] = child;
    25.             childnum++;
    26.         }
    27.     }
    28.  
    29.     // Update is called once per frame
    30.     void Update()
    31.     {
    32.         Collider[] colliders = Physics.OverlapSphere(gameObject.transform.position, 25f, layerMask: LayerMask.NameToLayer("Player"));
    33.         if (colliders.Length <1)
    34.         {
    35.             foreach (Transform waypoint in waypoints)
    36.             {
    37.                 agent.destination = waypoint.position;
    38.                 float distance = 0;
    39.                 while (!(distance > 0.1f))
    40.                 {
    41.                     distance = (gameObject.transform.position - waypoint.position).magnitude;
    42.                 }
    43.             }
    44.         }
    45.         else
    46.         {
    47.             agent.destination = Player.transform.position;
    48.         }
    49.     }
    50. }
    51.  
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,319
    We just had a talk about while loops in the other thread!!

    This is Spiney's post:

    https://forum.unity.com/threads/problem-with-de-bugging.1593597/#post-9834297



    You can't do what you're doing in line 39 above.

    That should probably be an if() statement, but again, not sure what exactly it is intended to do.

    It feels like perhaps that is a defective implementation of "find the nearest waypoint," or at least if that is what it is, it won't get you what you think...


    Unity will lock up 100% of the time EVERY millisecond your scripting code is running.

    Nothing will render, no input will be processed, no Debug.Log() will come out, no GameObjects or transforms will appear to update.

    Absolutely NOTHING will happen... until your code either:

    - returns from whatever function it is running

    - yields from whatever coroutine it is running

    As long as your code is looping, Unity isn't going to do even a single frame of change. Nothing.

    No exceptions.

    "Yield early, yield often, yield like your game depends on it... it does!" - Kurt Dekker


    Meanwhile, to fix your actual issue, you still need to learn how to debug:

    By debugging you can find out exactly what your program is doing so you can fix it.

    https://docs.unity3d.com/Manual/ManagedCodeDebugging.html

    Use the above techniques to get the information you need in order to reason about what the problem is.

    You can also use
    Debug.Log(...);
    statements to find out if any of your code is even running. Don't assume it is.

    Once you understand what the problem is, you may begin to reason about a solution to the problem.
     
    Bunny83 and spiney199 like this.
  3. Trussmister

    Trussmister

    Joined:
    Mar 24, 2024
    Posts:
    24
    Oh, regarding spiny, since this version of my code doesn't lock itself up i thought that its fixed and the useless while loop is so that the agent doesnt switch between waypoints every frame and only switches waypoints after it arrived at the previous waypoint, thanks.
     
  4. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    8,381
    It isn't locking up as your code is probably never entering the loop in your testing. As it stands, as soon as your code does enter that loop, it will go infinite and lock up the application.

    Again, you probably want this to be an if-statement, and not a while loop.
     
  5. Trussmister

    Trussmister

    Joined:
    Mar 24, 2024
    Posts:
    24
    Thanks
     
  6. Trussmister

    Trussmister

    Joined:
    Mar 24, 2024
    Posts:
    24
    I just fixed the while loop thing but the code is still broken, thanks.
     
    Last edited: May 15, 2024
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,319
    Yes, and ...

    See above.

    Writing code is easy. Silly easy. Anyone can do it.

    Debugging is where the actual work happens, where you actually make the code you wrote work.

    Again:

    By debugging you can find out exactly what your program is doing so you can fix it.

    https://docs.unity3d.com/Manual/ManagedCodeDebugging.html

    Use the above techniques to get the information you need in order to reason about what the problem is.

    You can also use
    Debug.Log(...);
    statements to find out if any of your code is even running. Don't assume it is.

    Once you understand what the problem is, you may begin to reason about a solution to the problem.
     
  8. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,183
    Since this is the second post on the same issue and I don't think the actual issue was understood in the first question, I like to point out some major problems and misunderstandings I see with this code.

    Update is a callback that is called by Unity once every frame. So that foreach loop inside the Update callback makes no sense. Unity's scripting layer is single threaded. So your Update method HAS TO finish within this frame or NOTHING in Unity will advance or react to anything. Unity hands over the control into your hands. Absolutely nothing is happening while your code is running. So it makes no sense to iterate through all waypoint inside Update. You would go through all waypoints within a single frame.

    For waypoint movement you either want to use a coroutine which can be interrupted / suspended so Unity can actually continue, or you want to remove all your loops and do your logic in Update. There are tons of examples for waypoint scripts on the internet. In general you want to remember the index of the current waypoint and in update you would just check how far you are from the current waypoint. When you reached the position you would increase the waypoint index in order to move to the next one. Of course it requires some additional checks what should happen once you reached the last one.
     
    spiney199 likes this.
  9. Trussmister

    Trussmister

    Joined:
    Mar 24, 2024
    Posts:
    24
    Thanks, this is my first rodeo so forgive me for my lack of understanding
     
  10. Trussmister

    Trussmister

    Joined:
    Mar 24, 2024
    Posts:
    24
    I rewrote to code and it partially works
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using Unity.AI.Navigation;
    4. using UnityEngine;
    5. using UnityEngine.AI;
    6.  
    7. public class EnemyLogic : MonoBehaviour
    8. {
    9.     public GameObject Player;
    10.     NavMeshAgent agent;
    11.     public Transform[] waypoints;
    12.     public int toWaypoint = 0;
    13.     public bool moving = false;
    14.     private bool personalSpottedEnemy;
    15.     private EnemiesManager enemiesManager;
    16.     void Start()
    17.     {
    18.         enemiesManager = GameObject.Find("GameManager").GetComponent<EnemiesManager>();
    19.         int childnum = 0;
    20.         agent = gameObject.GetComponent<NavMeshAgent>();
    21.         foreach (Transform child in GameObject.Find("Waypoints").transform)
    22.         {
    23.             childnum++;
    24.         }
    25.         waypoints = new Transform[childnum];
    26.         childnum = 0;
    27.         foreach (Transform child in GameObject.Find("Waypoints").transform)
    28.         {
    29.             waypoints[childnum] = child;
    30.             childnum++;
    31.         }
    32.     }
    33.  
    34.     // Update is called once per frame
    35.     void Update()
    36.     {
    37.         personalSpottedEnemy = false;
    38.         Collider[] colliders = Physics.OverlapSphere(gameObject.transform.position, 25f);
    39.         foreach (Collider collider in colliders)
    40.         {
    41.             if (collider.CompareTag("Player"))
    42.             {
    43.                 agent.destination = Player.transform.position;
    44.                 enemiesManager.SpottedPlayer=true;
    45.                 personalSpottedEnemy=true;
    46.             }
    47.         }
    48.         if (personalSpottedEnemy==false)
    49.         {
    50.             patrol();
    51.         }
    52.     }
    53.     void patrol()
    54.     {
    55.         if ((agent.gameObject.transform.position - waypoints[toWaypoint].position).magnitude < 1f)
    56.         {
    57.             if (toWaypoint > waypoints.Length)
    58.             {
    59.                 toWaypoint++;
    60.             }
    61.             else
    62.             {
    63.                 toWaypoint = 0;
    64.             }
    65.             moving = false;
    66.         }
    67.         if (moving == false)
    68.         {
    69.             agent.destination = waypoints[toWaypoint].position;
    70.             moving = true;
    71.         }
    72.     }
    73. }
    74.  
     
    Last edited: May 15, 2024