- Home /
How to generate Nav Mesh floor in a procedural generated maze?
Hello everyone, I'm new to Unity and I'm trying to add a Nav Mesh to the ground of my procedural generated maze (with some modifies of mine, I followed this tutorial: https://www.youtube.com/watch?v=OzENv_ZRA1g). I checked out in the internet and unfortunately it seemed that Unity doesn't support a dinamic Nav Mesh generation, but then I found out this: https://github.com/Unity-Technologies/NavMeshComponents which contains LocalNavMeshBuilder and NavMeshSourceTag scripts (watch this: https://www.youtube.com/watch?v=n6ilxlcNpgM).
I tried to attach these scripts to some of my components, generated dinamically during the build of the maze, in order to have a Nav Mesh floor, which was previously generated by instantiating many "little squares" ( cubes with a very low height) and parenting them to a "floorHolder" father.
This is NavigationGen function, contained in my Maze generator script, within the Start section.
void NavigationGen() {
Vector3 mazePos;
mazePos = wallHolder.transform.position;
NavMeshGenClone = Instantiate(NavMeshGen, mazePos, Quaternion.identity);
NavMeshGenClone.AddComponent<LocalNavMeshBuilder> ();
NavMeshGenClone.GetComponent<LocalNavMeshBuilder> ().m_Tracked = NavMeshGen.transform;
floorHolder.AddComponent<NavMeshSourceTag> ();
}
But when I run my scene, this solution doesn't work, and my NPC agent (a skeleton soldier) is unable to recognize a Nav Mesh floor. The error message is the following: Failed to create agent beacuse it is not close enough to the NavMesh.
Do you know how can I use proficiently these two scripts in order to make the floor of my maze a Nav Mesh? Thanks a lot!
UPDATE: Using a Parent object for the whole maze and applying the Nav$$anonymous$$eshSurface baker, I obtained this result. Here is the image, available from my Google Drive since I had some problems to upload it here on Unity Answers: https://drive.google.com/file/d/1WZF$$anonymous$$NNX81yd34Z6u1fAf5OI05EgNSZEh/view?usp=sharing
The problem is that the walls are not considered as obstacles, so the whole is blue colored. How can I fix this issue?
Great screenshot, it resolved all the questions I was going to ask at first! :)
The walls are deactivated, is that so when you are baking the navmesh? I just created a small test, and if the wall is deactivated when you bake the navmesh, it will not be taken into consideration.
UPDATE: here is the test project in google drive, maybe it can help. It is a similar setup, generating a (non-sensical) maze, then baking the navmesh.
Yeah, I did something similar right now, and the Nav$$anonymous$$eshSurface seems to work fine! However, my skeleton soldier seems always stuck in a certain point... maybe I should open another question for the Nav$$anonymous$$eshAgent! xD
Hi @Rizzutp, I also create the maze like you automatically, but I can't add the navmesh to it. Could you please help me solve the problem? $$anonymous$$any thanks in advance.
Hi @Dargor87, I have updated my answer with example code, try to use it for your solution.
Also, please do not write "I have the same problem" as answers, add them as comments. People who are interested in this questions will get notified and can look into your case.
Hi Harinezumi, thank you very much for the suggestion. I tried to use your code but, I didn't understand why, it gives me an error on nav$$anonymous$$eshComponents (it wants to make me generate it either as a variable or as a class). Regarding its use I don't understand how it works, should I use it where I go to generate the maze or should I attach it to the same gameobject to which the script that generates the maze is connected? $$anonymous$$any thanks in advance.
Answer by Harinezumi · Mar 16, 2018 at 01:14 PM
You can try using Unity NavMeshComponents (the manual page is here).
Unfortunately, the info on it is still lacking, but you can get the basics from the above pages and here. Basically once you have your maze constructed, use a NavMeshSurface
component to collect the geometry (either colliders or meshes) to use in your NavMesh, then use then call Bake()
on it. It may take a while for it to complete, partly depending on the complexity of your maze.
UPDATE
Here is a bit of code that will generate a navmesh from all the objects added to it for all the agent types you have defined.
Usage: set the list of game objects that are part of the navmesh with SetNavMeshElements()
, then call BuildNavMesh()
. Make sure that it runs before any of the NavMeshAgents are enabled, otherwise they will throw an error.
public class NavMeshGenerator : MonoBehaviour {
[SerializeField] private GameObject navMeshRoot = null;
private List<GameObject> navMeshElements = new List<GameObject>();
public void SetNavMeshElements(List<GameObject> values) {
navMeshComponents.Clear();
navMeshComponents.AddRange(values);
}
private void Awake () {
if (navMeshRoot == null) { navMeshRoot = new GameObject("NavMeshRoot"); }
}
public void BuildNavMesh () {
int agentTypeCount = NavMesh.GetSettingsCount();
if (agentTypeCount < 1) { return; }
for (int i = 0; i < navMeshElements.Count; ++i) { navMeshElements[i].transform.SetParent(navMeshRoot.transform, true); }
for (int i = 0; i < agentTypeCount; ++i) {
NavMeshBuildSettings settings = NavMesh.GetSettingsByIndex(i);
NavMeshSurface navMeshSurface = environment.AddComponent<NavMeshSurface>();
navMeshSurface.agentTypeID = settings.agentTypeID;
NavMeshBuildSettings actualSettings = navMeshSurface.GetBuildSettings();
navMeshSurface.useGeometry = NavMeshCollectGeometry.PhysicsColliders; // or you can use RenderMeshes
navMeshSurface.BuildNavMesh();
}
}
}
Basically it is what is reported in the tutorial posted previously, I think. However, thanks for linking the relative documentation pages, it was really appreciated ;-)
I'm trying to collect the floor squares in a Nav$$anonymous$$eshSurface array, but I'm obtaining this error message: Cannot implicitly convert type UnityEngine.GameObject[]
to UnityEngine.AI.Nav$$anonymous$$eshSurface[]
. How can I populate through script an array converting game Objects to Nav$$anonymous$$eshSurface type?
Ok, maybe this could save my day
for (int a = 0; a < objects.Length; a++) {
surfaces [a] = objects [a].GetComponent<Nav$$anonymous$$eshSurface> ();
}
No, it didn't work :-( Any help? Ah, I forgot to say that even my floorHolder is runtime generated
Answer by tormentoarmagedoom · Mar 16, 2018 at 10:03 AM
Good day. You should check this tutorial and this youtube videos.
Enjoy!
Accept the answer if helped :D
I'll check it out! Thanks. Are you sure that it will work with a floor constituted by so many little squares? $$anonymous$$aybe I should unify all the floor meshes in a unique single mesh? These are the things that worry me the most
It should work with small squares as well, but the baking time will probably be a lot faster if you combine your squares before baking.
Am I supposed to bake all the single squares before to apply the NavigationBaker script? P.s.: I'll try both procedures and check what happens in terms of performances :-)
Answer by Rizzutp · Mar 16, 2018 at 08:51 PM
UPDATE: I succeded in apply the Nav Mesh Surface to every single floor cell, but the Nav Mesh Surface is completely translated far away from its cell and I didn't understand why. Suggestions?
You can set the Nav$$anonymous$$eshSurface's center to be the same as your maze's center (position). You will need to either use world space or local space of them - it is not clear from the documentation which one it should be.
Is there any chance to set Nave$$anonymous$$eshSurface's center from script, since I baked every single floor cell in the editor to achieve the result reported in the previous image?
Your answer
Follow this Question
Related Questions
Making AI that can navigate through a city? 3 Answers
Making NavMesh areas? 0 Answers
How to prevent NavMeshAgents from colliding when warped to same position? 0 Answers
Why Nav Mesh Agent has been baked intermittently on 1 straight component? 0 Answers
How to change a NavMeshAgent angular rotation speed, 0 Answers