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): using UnityEngine; using System.Collections; using System; using UnityEngine.SceneManagement; using UnityEngine.AI; public class GameManager : MonoBehaviour { public GameObject DustStorm; private GameObject DustStormInstance; public Maze mazePrefab; public Canvas canvas; public Boolean pause = false; public GameObject PauseMenu; private Canvas canvasInstance; public Player playerPrefab; // public Spector SpectorPrefab; // public int WaitForSpector = 35; public Skulls Skulls; private Skulls skullsInstance; public int WaitForSkull = 35; public Pickup keyPrefab; private Pickup keyInstance; public int timeToWait = 50; // public Waypoint WayPointPrefab; // // private Waypoint WaypointInstance; private Maze mazeInstance; private Player playerInstance; private Spector SpectorInstance; [SerializeField] private int scene; private Timer Timer; private void Start () { StartCoroutine(BeginGame()); // surface.BuildNavMesh(); } void Update () { if (Input.GetKeyDown(KeyCode.P)) { if(pause == false) { Time.timeScale = 0; pause = true; Cursor.visible = true; PauseMenu.SetActive(true); } else { PauseMenu.SetActive(false); Cursor.visible = false; pause = false; Time.timeScale = 1; } //RestartGame(); } } public void Unpause() { PauseMenu.SetActive(false); Cursor.visible = false; pause = false; Time.timeScale = 1; } private IEnumerator BeginGame () { canvasInstance = Instantiate(canvas); Camera.main.clearFlags = CameraClearFlags.Skybox; Camera.main.rect = new Rect(0f, 0f, 1f, 1f); mazeInstance = Instantiate(mazePrefab) as Maze; yield return StartCoroutine(mazeInstance.Generate()); // DustStormInstance = Instantiate(DustStorm); playerInstance = Instantiate(playerPrefab) as Player; playerInstance.SetLocation(mazeInstance.GetCell(mazeInstance.RandomCoordinates)); // CreateWaypoints(10); Camera.main.clearFlags = CameraClearFlags.Depth; Camera.main.rect = new Rect(0f, 0f, 0.5f, 0.5f); yield return new WaitForSeconds(WaitForSkull); if (scene >= 3) { skullsInstance = Instantiate(Skulls) as Skulls; skullsInstance.SetLocation(mazeInstance.GetCell(mazeInstance.RandomCoordinates)); } if (scene >= 5) { CancelInvoke("skullsInstance"); } // yield return new WaitForSeconds(WaitForSpector); // SpectorInstance = Instantiate(SpectorPrefab) as Spector; // SpectorInstance.SetLocation(mazeInstance.GetCell(mazeInstance.RandomCoordinates)); // Spector(); yield return new WaitForSeconds(timeToWait); Pickup(); } /* private void CreateWaypoints(int Waypoint) { for (int i = 0; i < Waypoint; i++) { WaypointInstance = Instantiate(WayPointPrefab); WaypointInstance.SetLocation(mazeInstance.GetCell(mazeInstance.RandomCoordinates)); } } */ void Pickup() { keyInstance = Instantiate(keyPrefab) as Pickup; keyInstance.SetLocation(mazeInstance.GetCell(mazeInstance.RandomCoordinates)); } void Spector() { } public void RestartGame () { StopAllCoroutines(); Destroy(mazeInstance.gameObject); if (playerInstance != null) { Destroy(playerInstance.gameObject); } if (keyInstance != null) { Destroy(keyInstance.gameObject); } if(SpectorInstance != null) { Destroy(SpectorInstance.gameObject); } StartCoroutine(BeginGame()); } public void EndLevel() { AsyncOperation async = SceneManager.LoadSceneAsync(scene); } } AI Script Code (CSharp): using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; public class Skulls : MonoBehaviour { private Transform target; public int speed = 1; public Transform[] points; private int destPoint = 0; private NavMeshAgent agent; private int playerDistance; private MazeCell currentCell; private MazeDirection currentDirection; private float minRange; public void SetLocation(MazeCell cell) { if (currentCell != null) { currentCell.OnSpectorExited(); } currentCell = cell; transform.localPosition = cell.transform.localPosition; // currentCell.OnSpectorEntered(); } // Start is called before the first frame update void Start() { target = GameObject.FindGameObjectWithTag("Player").transform; Transform[] points = GameObject.FindGameObjectsWithTag("Waypiont").Transform; agent = GetComponent<NavMeshAgent>(); // Disabling auto-braking allows for continuous movement // between points (ie, the agent doesn't slow down as it // approaches a destination point). agent.autoBraking = false; GotoNextPoint(); } void OnTriggerEnter(Collider other) { if (other.tag == "Player") { Destroy(this); } } void GotoNextPoint() { // Returns if no points have been set up if (points.Length == 0) return; // Set the agent to go to the currently selected destination. agent.destination = points[destPoint].position; // Choose the next point in the array as the destination, // cycling to the start if necessary. destPoint = (destPoint + 1) % points.Length; } // Update is called once per frame void Update() { target = GameObject.FindGameObjectWithTag("Player").transform; transform.LookAt(target); // Choose the next destination point when the agent gets // close to the current one. if (!agent.pathPending && agent.remainingDistance < 0.5f) GotoNextPoint(); } }
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
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
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.
I've been trying that but the mesh links dont seem to help any it still shows up like that at runtime
You could build your navmesh on runtime like this: Code (CSharp): private void BuildNavMeshAtRuntime() { //TODO fill your list with obstacles and walkable/not walkable areas var buildSources = new List<NavMeshBuildSource>(); //Example with box colliders //TODO you have to do it for mesh colliders and capsule/sphere too var boxColliders = FindObjectsOfType<BoxCollider>(); foreach (var box in boxColliders) { var source = new NavMeshBuildSource(); source.shape = NavMeshBuildSourceShape.Box; source.size = box.size; source.transform = box.transform.localToWorldMatrix; source.area = 0; //0 Walkable, 1 Not walkable buildSources.Add(source); } //Configure build settings -> configure values for better performance and other results NavMeshBuildSettings buildSettings = NavMesh.GetSettingsByIndex(0); buildSettings.agentClimb = 0.3f; buildSettings.agentSlope = 35f; buildSettings.agentRadius = 0.4f; buildSettings.minRegionArea = 0.1f; buildSettings.agentHeight = 1f; buildSettings.overrideVoxelSize = true; buildSettings.voxelSize = 0.025f; //Build nav mesh var bounds = new Bounds(Vector3.zero, 10000.0f * Vector3.one); var navMeshData = NavMeshBuilder.BuildNavMeshData(buildSettings, buildSources, bounds, Vector3.zero, Quaternion.identity); navMeshData.name = "MyNavMeshAtRuntime"; var navMeshAdded = NavMesh.AddNavMeshData(navMeshData); }
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.