Search Unity

NavMesh.CreateSettings() not allowing changes

Discussion in 'Navigation' started by Multithreaded_Games, Sep 1, 2017.

  1. Multithreaded_Games

    Multithreaded_Games

    Joined:
    Jul 6, 2015
    Posts:
    122
    Came across a rather frustrating 'issue'. Basically, our game has several objects of varying radii and I want to do a processing step in the editor that basically searches for all of these entities and creates new build settings based on unique radii. Should be the easiest thing in the world, one would think...

    I am currently using NavMesh.CreateSettings() and in the inspector I can see that, indeed, new agent types are created in the Navigation pane. However, it doesn't seem like I can change any of the properties in code (hell, the 'name' property isn't exposed at all)

    Code (CSharp):
    1.  
    2. var buildSettings = NavMesh.CreateSettings();
    3. buildSettings.agentHeight = 10.0f; //Fake test value, doesn't change it in the inspector
    4.  
    5. var bs = (NavMesh.GetSettingsByID(buildSettings.agentTypeID)); //Neither does this
    6. bs.agentHeight = 12.0f;
    Is there some other step I need to complete (like a commit or something?) Am I even using this in the intended manner? I should also note that this isn't occurring at runtime (although it doesn't work then either) and is done via an inspector in the editor. Thanks!
     
    Harinezumi and Xepherys like this.
  2. Multithreaded_Games

    Multithreaded_Games

    Joined:
    Jul 6, 2015
    Posts:
    122
  3. Xype

    Xype

    Joined:
    Apr 10, 2017
    Posts:
    339
    Code (CSharp):
    1. // Get Total Number Of Agent Types
    2.         int bs = NavMesh.GetSettingsCount();
    3.      
    4.         // Loop Through Each Agent Type And Set Height
    5.         for (int i = 0; i <= bs; ++i)
    6.         {
    7.             // Set Agent Types Height
    8.             NavMesh.GetSettingsByID(i).agentHeight = 10.0f;
    9.          
    10.             // Note there is a Name Field
    11.             // NavMesh.GetSettingsNameFromID(i);
    12.         }
    Sorry for the delay, I totally gave you the wrong thing the first time, had to go back and get the right thing haha. Unity docs are so terribly bad. They say here there is this variable. Enjoy but tell you jack about it.

    Yes you can use foreach, while, whatever you want. If you only have 1 to set no need for a loop. Just providing solid example and I am old school I like my funky long loops.
     
  4. Multithreaded_Games

    Multithreaded_Games

    Joined:
    Jul 6, 2015
    Posts:
    122
    Hey @Xype,

    I've actually tried this method--does this code actually compile for you? When I try it, I get this error:

    'Error CS1612: Cannot modify a value type return value of `UnityEngine.AI.NavMesh.GetSettingsByID(int)'. Consider storing the value in a temporary variable'

    Is it possible that I perhaps have an outdated version of the new NavMesh components API? I assumed that there was only one version and that it was up-to-date...
     
  5. Xype

    Xype

    Joined:
    Apr 10, 2017
    Posts:
    339
    To be perfectly honest I did not try to compile. I was looking for no errors. However looking at that....I used a get method and tried to set, which may be the problem.... That should get you in the general area, maybe try getting to get the buildsettings then set it from there....


    Code (CSharp):
    1.  
    2. NavMeshBuildSettings buildSet = NavMesh.GetSettingsByID(i);
    3. buildSet.agentHeight = 10.0f;
    4.  
    Again untested but it should have you in the right space, intellisense should help guide you but you will have to poke around since what you need to access isn't in the open source area.
     
  6. Multithreaded_Games

    Multithreaded_Games

    Joined:
    Jul 6, 2015
    Posts:
    122
    @Xype

    Maybe I wasn't clear enough, but the problem isn't with finding what code to modify--it's the fact that these changes are not actually 'committed.' The code you provided in your latest post is essentially what I posted to begin with :p

    Basically, I can see the new settings being created and added in the "Agents" section of the Navigation pane when I call CreateSettings(). The problem is that changing properties (agentHeight, for instance) in code seem to have no effect on the state of the actual object that is shown in the Inspector. This leads me to believe that the object that I am getting from "GetSettingsByID" is a 'copy' of the object and not the original, thus changes made to it are not reflected in the object as shown in the Inspector. Couple this with the error given by trying to access it directly and it seems to indicate that these cannot be changed in code. For now, I'm just updating them in the Inspector manually--thanks for your help anyhow!
     
  7. Xepherys

    Xepherys

    Joined:
    Sep 9, 2012
    Posts:
    204
    You're correct in your assumption - you aren't getting a reference to the settings, but a copy of them. What you would need would be a byref option, like:

    NavMeshBuildSettings buildSet = ref NavMesh.GetSettingsByID(i);​

    However, that's only available in C# 7, which Mono hasn't rolled in yet. There's even a Unity forum post about it (very roughly) in the 2017 beta forum where this specific thing was discussed:

    https://forum.unity.com/threads/c-7.468585/

    So, if you build the NavMesh programmatically, your settings should take (I modify buildsettings after grabbing from an agent and it works fine), but it won't reflect in the inspector. Even with byref declarations, it's possible that a private or protected value in Unity's editor code would prevent this from being set anyhow, though you'd see an exception to that effect and know that was happening.
     
  8. Multithreaded_Games

    Multithreaded_Games

    Joined:
    Jul 6, 2015
    Posts:
    122
    @Xepherys,

    Thanks for the detailed response! Just to clarify, is it possible to use C#7 at all with Unity at the moment? (Even using Visual Studio?)
     
  9. Xepherys

    Xepherys

    Joined:
    Sep 9, 2012
    Posts:
    204
    Well, in that Unity Forum link above, one user talks about compiling the code to DLLs first and then just calling those DLLs. That seems like a real hassle unless you absolutely need the feature. I know that Unity has been really pushing to work more closely with the Mono group, so it's possible we'll see faster turnaround of new versions of Mono available for Unity. Of course, Mono themselves have not added C#7, as far as I know, so no matter how quickly Unity can turn it around, it isn't available at all currently.

    What I've been doing instead is using an override for values in a separate script. My AI foundation is built off of Dungeon Architect. I've rewritten some large chunks of it, but it was a great foundation. I'm doing this:



    So I have two agents and need to build runtime meshes for both. I also want to override the tile size which can't be done in the Unity Nav UI anyway. I could extend this to add other values and override them prior to instantiation.

    Side note - I came here earlier looking for ways to enumerate all available agents by ID and name because those IDs are a pain to find. I didn't find one, so the Nav Agent ID is just set via an enum that I'll have to manually update with each new Agent, finding it's ID by instantiating it and setting a break point so I can view it from code. This should NOT be such a PITA.
     
  10. Xype

    Xype

    Joined:
    Apr 10, 2017
    Posts:
    339
    What I posted goes through existing id's to find them, your code which you are claiming is the same creates a new setting set, not the same at all.
     
  11. Xepherys

    Xepherys

    Joined:
    Sep 9, 2012
    Posts:
    204
    I didn't claim it was the same. I said "what I've been doing instead is". The point also is that my particular needs were to modify settings at runtime with values from the inspector just before the navMesh was generated.

    And really, your code doesn't do anything because you can't set the value back to the reference of the settings (in current Unity it's simply not possible). You would ALSO have to create a new copy of the settings and change the values before feeding it to the navMesh build routines. The reason @Multithreaded_Games doesn't see the change in the inspector is because... there's no change to be seen. As much as Unity naming sometimes doesn't make sense, in this case it's clear. GETSettingsById, not SETSettingsById. You aren't getting a reference, you're getting a copy.
     
  12. Harinezumi

    Harinezumi

    Joined:
    Jan 7, 2013
    Posts:
    54
    @Multithreaded_Games, I have the same issue, I'm trying to use NavMesh.CreateSettings() to be able to create agent types run-time. However, the settings cannot be assigned to the NavMeshSurface, and modifying the values is not allowed. I think the API is simply broken.

    I think Xype's solution works for them, because they already have the agent types (that define the NavMeshBuildSettings) declared in their project, and that's why NavMesh.GetSettingsByIndex() works for them (note that it should be GetSettingsByIndex(), not GetSettingsByID() - if you use the second one, you will likely get some error, because the settings IDs are NOT "linear").

    So does anyone have a solution for creating agent types at run-time (without it being defined in Editor)?
     
  13. mateuszwallace

    mateuszwallace

    Joined:
    Dec 13, 2019
    Posts:
    17
    Well you can change some properties of baking proces runtime using navMeshSurface component.

    When you call a function BuildNavMesh() try modify it to pass argument like radius BuildNavMesh(radius), next pass this to GetBuildSettings(radius) and finally in body above return buildSetting add what you want to modify for example:


    if (radius != 0)
    {
    buildSettings.agentRadius = radius;
    }

    .
     
  14. pdinklag

    pdinklag

    Joined:
    Jan 24, 2017
    Posts:
    154
    This API is completely useless. As others have noticed, it returns a copy of a struct, there is no way to change anything per script. Nothing is exposed to C#, so not even reflection tricks are going to work here. It really appears that the API is used solely for the editor (it is used here) and not even intended for actual use at runtime. More reasons to switch to a third party solution...
     
    adrien_guillemot likes this.
  15. adrien_guillemot

    adrien_guillemot

    Joined:
    Oct 4, 2021
    Posts:
    4
    Which third party solution are you talking about ? A* ? Maybe another one ?

    I'm struggling hard to modify the Navigation Agent Settings (like agentRadius) but it seems impossible in runtime with this API.
     
  16. pdinklag

    pdinklag

    Joined:
    Jan 24, 2017
    Posts:
    154
    It is.

    Indeed.

    Although now that I have some experience with that, A* has very obvious downsides. For being a top selling and extremely popular asset on the store, its documentation isn't very clear about what works with what graph types, it hasn't been updated in ages, the forum is an utter mess and the API design is horrible in many many ways. Still, the backend works very well, it is very fast, the asset is very customizable and the source code is included so you can change whatever you need changed.

    A* is definitely better than Unity's nav meshes and it's probably the go-to solution for pathfinding, especially regarding the lack of alternatives. But I also think it's getting a little too much praise seeing how much of a mess it is.
     
    adrien_guillemot likes this.