News Forums Troubleshooting How to check point is on the nav mesh?

This topic contains 22 replies, has 4 voices, and was last updated by  abchiptop 9 months ago.

Viewing 15 posts - 1 through 15 (of 23 total)
  • Author
    Posts
  • #8272

    zcoldrick
    Participant

    I used the following script to create a wander location similar to that described in the wander tutorial but having to add an extra float to the OnGraph method.

    However the an.Navigator.OnGraph(loc, 0f);

    part doesn’t function as I expect.

    I thought this would only return true if the location was on the nav mesh however I seem to be getting locations way off it.

    My script creates a cube at the location for visualization purposes.

    
    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    using RAIN.Core;
    using RAIN.Action;
    [RAINAction("Choose Wander Location")]
    public class AIChooseWanderLocation : RAINAction
    {
        public AIChooseWanderLocation()
        {
            actionName = "AIChooseWanderLocation";
        }
        public override void Start(AI ai)
        {
            base.Start(ai);
        }
        public override ActionResult Execute(AI ai)
        {
    		Vector3 loc = Vector3.zero;
    		do {
    			loc = new Vector3(Mathf.Clamp(ai.Kinematic.Position.x + Random.Range(-15f, 15f), -25f, 25f),
    			                  ai.Kinematic.Position.y,
    			                  Mathf.Clamp(ai.Kinematic.Position.z + Random.Range(-15f, 15f), -25f, 25f));
    				} while ((Vector3.Distance(ai.Kinematic.Position, loc) < 5f) || !ai.Navigator.OnGraph(loc,0f));
    		ai.WorkingMemory.SetItem<Vector3> ("wanderTarget", loc);
    		// create cube at position
    		GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
    		//cube.AddComponent<Rigidbody>();
    		cube.transform.position = loc;
            return ActionResult.SUCCESS;
        }
        public override void Stop(AI ai)
        {
            base.Stop(ai);
        }
    }

    Is there a better way to check the point is reachable? additionally the mesh has generated some unconnected nav mesh regions that it is possible this point would appear on… however my character wouldn’t be able to get to them. Is there a way to check if the point is reachable rather than just checking if it is “on the nav mesh”.

    #8351

    marcfielding
    Participant

    Its a bit of an odd one this, it seems that the AI doesn’t start with a Navigation Mesh attached and doesn’t pick it up for a few cycles which means OnGraph will always return true with no NavMesh.

    To fix the problem add this line to your Start() function in your action….

    I’m lazy and am testing so my navigation mesh is called “Navigation Mesh” i’d assume yours is possibly the same!

    public override void Start(AI ai)
    {
    base.Start(ai);
    ai.Navigator.CurrentGraph = NavigationManager.instance.GetNavigationGraph (“Navigation Mesh”);

    }

    Your cubes should now appear on the graph all the time!

    Good Luck

    Marc

    #8398

    prime
    Keymaster

    RAIN 2.0.10 should automatically grab a navmesh on start - you don’t need to add that code anymore.

    The code you are using is from the first tutorial I put together - and I’m wishing I had put more thought into it before i posted the code. It isn’t the best implementation.

    1) Get rid of the Clamp functions. They are just going to cause problems
    2) Instead of OnGraph, you should check

    NavigationManager.instance.GetGraphsForPoints(ai.Kinematic.Position, loc, ai.Motor.StepUpHeight, GraphType.NavMesh, ((BasicNavigate)ai.Navigator).GraphTags).Count > 0
    #8403

    marcfielding
    Participant

    Not that i’m chasing you about the forums here Prime but I think I better stop answering questions, thats two for two I was wrong on!

    Although I would say Debug.Log(ai.Navigator.CurrentGraph) right after base.Start(ai) was showing Null this afternoon for me which is why I came round to that solution which I found elsewhere on the forum. I’m definitely on the latest version of rain.

    #8413

    prime
    Keymaster

    The graph isn’t necessarily non-null immediately. However, there is a new check on the Navigator to force a refresh of the mesh before allowing any pathfinding functions to run. So it would happen right before the first Move call or the first OnGraph check, for example.

    #8445

    zcoldrick
    Participant

    Hello,

    I replaced the while condition to :

    
    while ((Vector3.Distance(ai.Kinematic.Position, loc) < 5f) || (NavigationManager.instance.GetGraphsForPoints(ai.Kinematic.Position, loc, ai.Motor.StepUpHeight, GraphType.NavMesh, ((BasicNavigate)ai.Navigator).GraphTags).Count > 0));

    As suggested but the compiler can’t find NavigationManager.

    Any ideas ?

    EDIT:

    I added using RAIN.Navigation; to the top of the script. it finds the NavigationManager but doesn’t have a .instance.GetGraphsForPoints member?

    • This reply was modified 9 months, 4 weeks ago by  zcoldrick.
    #8449

    marcfielding
    Participant

    I have the same issue, just messing around with it now, I can’t see a GetGraphsForPoints method in the documentation, there is however a GraphsForPoints. Give me 20 and i’ll post back, again i’m no expert but we happen to be working on the same thing!

    #8452

    marcfielding
    Participant

    Yeah i’m not even going to make a suggestion on that, will wait for Prime to get back.

    #8471

    prime
    Keymaster

    You need a using statement.

    using RAIN.Navigation;
    #8474

    marcfielding
    Participant

    I have that already…

    Code is as follows:

    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    using RAIN.Core;
    using RAIN.Action;
    using RAIN.Navigation;
    [RAINAction]
    public class ChoseWanderLocation : RAINAction
    {
        public ChoseWanderLocation()
        {
            actionName = "ChoseWanderLocation";
        }
        public override void Start(AI ai)
        {
            base.Start(ai);
    		//ai.Navigator.CurrentGraph = NavigationManager.instance.GetNavigationGraph ("Navigation Mesh");
    	}
    	public override ActionResult Execute(AI ai)
    	{
    		Vector3 loc = Vector3.zero;
    		do {
    			loc = Vector3.zero;
    			loc = new Vector3(Mathf.Clamp(ai.Kinematic.Position.x * Random.Range (-20f,20f),-30f,30f),
    			                  ai.Kinematic.Position.y,
    			                  Mathf.Clamp(ai.Kinematic.Position.z * Random.Range (-20f,20f),-30f,30f));
    		} while ((Vector3.Distance(ai.Kinematic.Position, loc) < 5f) || (NavigationManager.instance.GetGraphsForPoints(ai.Kinematic.Position, loc, ai.Motor.StepUpHeight, GraphType.NavMesh, ((BasicNavigate)ai.Navigator).GraphTags).Count > 0));
    		//while ((Vector3.Distance (ai.Kinematic.Position , loc) < 5f)|| !ai.Navigator.OnGraph(loc,0f));
    		ai.WorkingMemory.SetItem<Vector3> ("wanderTarget", loc);
    		return ActionResult.SUCCESS;
    	}
    

    Error thats given:

    
    Assets/AI/Actions/ChoseWanderLocation.cs(36,109): error CS1061: Type RAIN.Navigation.NavigationManager does not contain a definition for GetGraphsForPoints and no extension method  GetGraphsForPoints of type RAIN.Navigation.NavigationManager could be found (are you missing a using directive or an assembly reference?)
    

    If I change GetGraphsForPoints for GraphsForPoints I then get:
    1)

    
    Assets/AI/Actions/ChoseWanderLocation.cs(36,176): error CS0103: The name GraphType does not exist in the current context
    

    2)

    
    Assets/AI/Actions/ChoseWanderLocation.cs(36,197): error CS0246: The type or namespace name BasicNavigate could not be found. Are you missing a using directive or an assembly reference?
    

    3)

    
    Assets/AI/Actions/ChoseWanderLocation.cs(36,109): error CS1502: The best overloaded method match for

    RAIN.Navigation.NavigationManager.GraphsForPoints(UnityEngine.Vector3, UnityEngine.Vector3, float, RAIN.Navigation.NavigationManager.GraphType, System.Collections.Generic.List<string>)’ has some invalid arguments

    
    4)
    

    Assets/AI/Actions/ChoseWanderLocation.cs(36,109): error CS1503: Argument #4 cannot convert object expression to type RAIN.Navigation.NavigationManager.GraphType
    `

    • This reply was modified 9 months, 4 weeks ago by  marcfielding.
    • This reply was modified 9 months, 4 weeks ago by  marcfielding.
    • This reply was modified 9 months, 4 weeks ago by  marcfielding. Reason: trying to sort formatting from unity error console
    • This reply was modified 9 months, 4 weeks ago by  marcfielding.
    • This reply was modified 9 months, 4 weeks ago by  marcfielding.
    #8486

    prime
    Keymaster

    The code should be

    NavigationManager.instance.GraphsForPoints

    The “GetGraphsForPoints” is a typo.

    • This reply was modified 9 months, 4 weeks ago by  prime.
    #8491

    marcfielding
    Participant

    Hi Prime,

    I appreciate your really busy and probably flying through these but I said in my post I made that swap, theres a list of after that!

    Thanks

    Marc

    #8499

    prime
    Keymaster

    Hmm. Too many typos.

    “BasicNavigate” should be BasicNavigator.

    GraphType should be NavigationManager.GraphType

    #8507

    zcoldrick
    Participant

    The following scripts works, until the object target appears under a create (using the mechanim tutorial green crate scene).

    When this happens the character walks up to it and either stops or the game crashes.

    Until that happens, the character walks from target to new target quite happily.

    
    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    using RAIN.Core;
    using RAIN.Action;
    using RAIN.Navigation;
    [RAINAction("Choose Wander Location")]
    public class AIChooseWanderLocation : RAINAction
    {
    	// add in a cube and rename Indicator to display target location
    	private GameObject Indicator;
        public AIChooseWanderLocation()
        {
            actionName = "AIChooseWanderLocation";
        }
        public override void Start(AI ai)
        {
            base.Start(ai);
    		Indicator = GameObject.Find ("Indicator");
        }
        public override ActionResult Execute(AI ai)
        {
    		Vector3 loc = Vector3.zero;
    		do {
    			loc = new Vector3(ai.Kinematic.Position.x + Random.Range(-8f, 8f),
    			                  ai.Kinematic.Position.y,
    			                  ai.Kinematic.Position.z + Random.Range(-8f, 8f));
    				} while ((Vector3.Distance(ai.Kinematic.Position, loc) < 5f) || !(NavigationManager.instance.GraphsForPoints(ai.Kinematic.Position, loc, ai.Motor.StepUpHeight, NavigationManager.GraphType.Navmesh, ((BasicNavigator)ai.Navigator).GraphTags).Count > 0 ));
    		//if CharacterStepUpHeight is set correctly you that in graphsforpoints third parameter instead of 0f 
    		ai.WorkingMemory.SetItem<Vector3> ("wanderTarget", loc);
    		// create cube at position
    		Indicator.transform.position = loc;
            return ActionResult.SUCCESS;
        }
        public override void Stop(AI ai)
        {
            base.Stop(ai);
        }
    }
    #8551

    zcoldrick
    Participant

    The previous code only works for a short time because I’m ‘Inverting’ the output of :

    (NavigationManager.instance.GraphsForPoints(ai.Kinematic.Position, loc, ai.Motor.StepUpHeight, NavigationManager.GraphType.Navmesh, ((BasicNavigator)ai.Navigator).GraphTags).Count > 0 )

    When this returns true unity crashes.

    This clearly isn’t the function my droids are looking for.

    Ideally I just want a function such like:

    isOnMesh(Vector3 transform, bool ignoreY)

    which would return true if the point was on the mesh or false if not, the ignore y would allow it to just check the x and z coordinates so that height issues with the initial object were ignored.

    OR:

    isValidPath(Vector3 transform1, Vector3 transform2, float setupheight, (unknown type) navmesh, (unknown type) ignoreTags)

    Ideally this should return true if a valid path exists between transform1 and transform2 and false if not.

    This last one would be similar to that function GraphsForPoints() but have a more obvious return type. I can’t work out what the return type for it is and the .count member variable isn’t obvious to me.

Viewing 15 posts - 1 through 15 (of 23 total)

You must be logged in to reply to this topic.