Search Unity

AI Waypoint issues

Discussion in 'Scripting' started by BatgirlDee, Jun 14, 2019.

  1. BatgirlDee

    BatgirlDee

    Joined:
    Mar 20, 2019
    Posts:
    36
    i have this script which creates waypoints in random locations withing the randomly generated maze
    but the AI script does not find them or follow them so i'm wondering if anyone could help solve this

    here are the scripts

    Script which creates waypoints

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using System;
    5. using UnityEngine.SceneManagement;
    6. using UnityEngine.AI;
    7.  
    8.  
    9. public class GameManager : MonoBehaviour {
    10.  
    11.     public GameObject DustStorm;
    12.  
    13.     private GameObject DustStormInstance;
    14.  
    15.     public Maze mazePrefab;
    16.  
    17.     public Canvas canvas;
    18.     public Boolean pause = false;
    19.  
    20.     public GameObject PauseMenu;
    21.  
    22.     private Canvas canvasInstance;
    23.  
    24.     public Player playerPrefab;
    25.  
    26.     //   public Spector SpectorPrefab;
    27.  
    28.     //   public int WaitForSpector = 35;
    29.  
    30.     public Skulls Skulls;
    31.     private Skulls skullsInstance;
    32.     public int WaitForSkull = 35;
    33.  
    34.     public Pickup keyPrefab;
    35.  
    36.     private Pickup keyInstance;
    37.  
    38.     public int timeToWait = 50;
    39.  
    40.   //  public Waypoint WayPointPrefab;
    41.   //
    42.   //  private Waypoint WaypointInstance;
    43.  
    44.     private Maze mazeInstance;
    45.  
    46.     private Player playerInstance;
    47.  
    48.     private Spector SpectorInstance;
    49.  
    50.  
    51.  
    52.     [SerializeField]
    53.     private int scene;
    54.  
    55.     private Timer Timer;
    56.  
    57.     private void Start () {
    58.  
    59.         StartCoroutine(BeginGame());
    60.  
    61.    //     surface.BuildNavMesh();
    62.     }
    63.    
    64.      void Update () {
    65.  
    66.         if (Input.GetKeyDown(KeyCode.P)) {
    67.    
    68.             if(pause == false)
    69.             {
    70.                 Time.timeScale = 0;
    71.                 pause = true;
    72.                 Cursor.visible = true;
    73.                 PauseMenu.SetActive(true);
    74.             }
    75.             else
    76.             {
    77.                 PauseMenu.SetActive(false);
    78.                 Cursor.visible = false;
    79.                 pause = false;
    80.                 Time.timeScale = 1;
    81.             }
    82.             //RestartGame();
    83.         }
    84.  
    85.      
    86.     }
    87.  
    88.  
    89.     public void Unpause()
    90.     {
    91.         PauseMenu.SetActive(false);
    92.         Cursor.visible = false;
    93.         pause = false;
    94.         Time.timeScale = 1;
    95.     }
    96.  
    97.     private IEnumerator BeginGame () {
    98.         canvasInstance = Instantiate(canvas);
    99.         Camera.main.clearFlags = CameraClearFlags.Skybox;
    100.         Camera.main.rect = new Rect(0f, 0f, 1f, 1f);
    101.         mazeInstance = Instantiate(mazePrefab) as Maze;
    102.         yield return StartCoroutine(mazeInstance.Generate());
    103.  
    104.      //   DustStormInstance = Instantiate(DustStorm);
    105.         playerInstance = Instantiate(playerPrefab) as Player;
    106.         playerInstance.SetLocation(mazeInstance.GetCell(mazeInstance.RandomCoordinates));
    107.  
    108.     //    CreateWaypoints(10);
    109.  
    110.         Camera.main.clearFlags = CameraClearFlags.Depth;
    111.         Camera.main.rect = new Rect(0f, 0f, 0.5f, 0.5f);
    112.  
    113.         yield return new WaitForSeconds(WaitForSkull);
    114.         if (scene >= 3)
    115.         {
    116.             skullsInstance = Instantiate(Skulls) as Skulls;
    117.             skullsInstance.SetLocation(mazeInstance.GetCell(mazeInstance.RandomCoordinates));
    118.         }
    119.         if (scene >= 5)
    120.         {
    121.             CancelInvoke("skullsInstance");
    122.         }
    123.  
    124.  
    125.  
    126.         //    yield return new WaitForSeconds(WaitForSpector);
    127.         //    SpectorInstance = Instantiate(SpectorPrefab) as Spector;
    128.         //    SpectorInstance.SetLocation(mazeInstance.GetCell(mazeInstance.RandomCoordinates));
    129.         // Spector();
    130.  
    131.         yield return new WaitForSeconds(timeToWait);
    132.         Pickup();
    133.  
    134.        
    135.  
    136.     }
    137.  
    138. /*   private void CreateWaypoints(int Waypoint)
    139.     {
    140.         for (int i = 0; i < Waypoint; i++)
    141.         {
    142.             WaypointInstance = Instantiate(WayPointPrefab);
    143.             WaypointInstance.SetLocation(mazeInstance.GetCell(mazeInstance.RandomCoordinates));
    144.         }
    145.     }
    146.  
    147.     */
    148.     void Pickup()
    149.     {
    150.        
    151.         keyInstance = Instantiate(keyPrefab) as Pickup;
    152.         keyInstance.SetLocation(mazeInstance.GetCell(mazeInstance.RandomCoordinates));
    153.     }
    154.  
    155.     void Spector()
    156.     {
    157.        
    158.  
    159.     }
    160.     public void RestartGame () {
    161.         StopAllCoroutines();
    162.         Destroy(mazeInstance.gameObject);
    163.         if (playerInstance != null) {
    164.             Destroy(playerInstance.gameObject);
    165.         }
    166.         if (keyInstance != null)
    167.         {
    168.             Destroy(keyInstance.gameObject);
    169.         }
    170.        
    171.         if(SpectorInstance != null)
    172.         {
    173.             Destroy(SpectorInstance.gameObject);
    174.         }
    175.         StartCoroutine(BeginGame());
    176.     }
    177.  
    178.     public void EndLevel()
    179.     {
    180.         AsyncOperation async = SceneManager.LoadSceneAsync(scene);
    181.     }
    182.  
    183.  
    184. }
    AI Script
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.AI;
    5.  
    6.  
    7. public class Skulls : MonoBehaviour
    8. {
    9.     private Transform target;
    10.  
    11.     public int speed = 1;
    12.  
    13.     public Transform[] points;
    14.     private int destPoint = 0;
    15.     private NavMeshAgent agent;
    16.  
    17.     private int playerDistance;
    18.     private MazeCell currentCell;
    19.  
    20.     private MazeDirection currentDirection;
    21.     private float minRange;
    22.  
    23.     public void SetLocation(MazeCell cell)
    24.     {
    25.         if (currentCell != null)
    26.         {
    27.             currentCell.OnSpectorExited();
    28.         }
    29.         currentCell = cell;
    30.         transform.localPosition = cell.transform.localPosition;
    31.        // currentCell.OnSpectorEntered();
    32.     }
    33.  
    34.  
    35.     // Start is called before the first frame update
    36.     void Start()
    37.     {
    38.         target = GameObject.FindGameObjectWithTag("Player").transform;
    39.  
    40.         Transform[] points = GameObject.FindGameObjectsWithTag("Waypiont").Transform;
    41.  
    42.         agent = GetComponent<NavMeshAgent>();
    43.  
    44.         // Disabling auto-braking allows for continuous movement
    45.         // between points (ie, the agent doesn't slow down as it
    46.         // approaches a destination point).
    47.         agent.autoBraking = false;
    48.  
    49.         GotoNextPoint();
    50.  
    51.     }
    52.  
    53.  
    54.     void OnTriggerEnter(Collider other)
    55.     {
    56.         if (other.tag == "Player")
    57.         {
    58.             Destroy(this);
    59.         }
    60.     }
    61.     void GotoNextPoint()
    62.     {
    63.         // Returns if no points have been set up
    64.         if (points.Length == 0)
    65.             return;
    66.  
    67.         // Set the agent to go to the currently selected destination.
    68.         agent.destination = points[destPoint].position;
    69.  
    70.         // Choose the next point in the array as the destination,
    71.         // cycling to the start if necessary.
    72.         destPoint = (destPoint + 1) % points.Length;
    73.     }
    74.  
    75.     // Update is called once per frame
    76.     void Update()
    77.     {
    78.         target = GameObject.FindGameObjectWithTag("Player").transform;
    79.  
    80.         transform.LookAt(target);
    81.  
    82.         // Choose the next destination point when the agent gets
    83.         // close to the current one.
    84.         if (!agent.pathPending && agent.remainingDistance < 0.5f)
    85.             GotoNextPoint();
    86.  
    87.  
    88.  
    89.     }
    90. }
     
  2. WallaceT_MFM

    WallaceT_MFM

    Joined:
    Sep 25, 2017
    Posts:
    394
    NavMeshAgents use NavMesh to understand the world and pathfind. If you are randomly generating your mazes, you will also need to generate navigation meshes for your agents. How you do that will depend on how you are generating your mazes. Here's a starting point in the docs: https://docs.unity3d.com/Manual/NavMesh-BuildingComponents.html
     
  3. BatgirlDee

    BatgirlDee

    Joined:
    Mar 20, 2019
    Posts:
    36
    thanks i'll have a look. i did use a surface navmash within the scene i suppose there could be a better way to implement it

    this is what i'm getting at the moment

    NavPic.png
     
    Last edited: Jun 15, 2019
  4. WallaceT_MFM

    WallaceT_MFM

    Joined:
    Sep 25, 2017
    Posts:
    394
    Looks like the mesh isn't generating well. The agents will think that only those blue spots are walkable, so they won't be able to get from room to room. If you are using prefabs, you could bake the mesh into the prefabs and then try stitching them together when they are generated with NavMesh Links.
     
  5. BatgirlDee

    BatgirlDee

    Joined:
    Mar 20, 2019
    Posts:
    36
    I've been trying that but the mesh links dont seem to help any it still shows up like that at runtime
     
  6. ClaudiaTheDev

    ClaudiaTheDev

    Joined:
    Jan 28, 2018
    Posts:
    331
    You could build your navmesh on runtime like this:

    Code (CSharp):
    1.    private void BuildNavMeshAtRuntime()
    2.         {
    3.             //TODO fill your list with obstacles and walkable/not walkable areas
    4.             var buildSources = new List<NavMeshBuildSource>();
    5.  
    6.             //Example with box colliders
    7.             //TODO you have to do it for mesh colliders and capsule/sphere too
    8.             var boxColliders = FindObjectsOfType<BoxCollider>();
    9.             foreach (var box in boxColliders)
    10.             {
    11.                 var source = new NavMeshBuildSource();
    12.                 source.shape = NavMeshBuildSourceShape.Box;
    13.                 source.size = box.size;
    14.                 source.transform = box.transform.localToWorldMatrix;
    15.                 source.area = 0; //0 Walkable, 1 Not walkable
    16.                 buildSources.Add(source);
    17.             }
    18.  
    19.             //Configure build settings -> configure values for better performance and other results
    20.             NavMeshBuildSettings buildSettings = NavMesh.GetSettingsByIndex(0);
    21.             buildSettings.agentClimb = 0.3f;
    22.             buildSettings.agentSlope = 35f;
    23.             buildSettings.agentRadius = 0.4f;
    24.             buildSettings.minRegionArea = 0.1f;
    25.             buildSettings.agentHeight = 1f;
    26.             buildSettings.overrideVoxelSize = true;
    27.             buildSettings.voxelSize = 0.025f;
    28.  
    29.             //Build nav mesh
    30.             var bounds = new Bounds(Vector3.zero, 10000.0f * Vector3.one);
    31.             var navMeshData = NavMeshBuilder.BuildNavMeshData(buildSettings, buildSources, bounds, Vector3.zero, Quaternion.identity);
    32.             navMeshData.name = "MyNavMeshAtRuntime";
    33.  
    34.             var navMeshAdded = NavMesh.AddNavMeshData(navMeshData);
    35.         }
     
  7. BatgirlDee

    BatgirlDee

    Joined:
    Mar 20, 2019
    Posts:
    36
    Ok I'll give it ago and thanks do I put this on my maze prefab or on it's own object
     
  8. ClaudiaTheDev

    ClaudiaTheDev

    Joined:
    Jan 28, 2018
    Posts:
    331
    You can put it whereever you like (your maze prefab too), just get sure that the navmesh is build before determining the waypoints and placing the agents/enemies. So you have to find the place in your code when the function has to be called. Also you should clear previous NavMeshData.
     
  9. BatgirlDee

    BatgirlDee

    Joined:
    Mar 20, 2019
    Posts:
    36
    okie dokie thanks
     
  10. BatgirlDee

    BatgirlDee

    Joined:
    Mar 20, 2019
    Posts:
    36


    this is whats happening as you can see the navmesh is being built while the maze is being generated