Search Unity

  1. Check out the Unite LA keynote for updates on the Visual Effect Editor, the FPS Sample, ECS, Unity for Film and more! Watch it now!
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  4. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  5. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

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:
    117
    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:
    117
  3. Xype

    Xype

    Joined:
    Apr 10, 2017
    Posts:
    315
    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:
    117
    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:
    315
    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:
    117
    @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:
    178
    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:
    117
    @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:
    178
    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:
    315
    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:
    178
    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:
    43
    @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)?