News Forums RAIN General Discussion and Troubleshooting Exporting NavMesh For Server Pathfinding

This topic contains 7 replies, has 2 voices, and was last updated by  Sigil 10 months, 1 week ago.

Viewing 8 posts - 1 through 8 (of 8 total)
  • Author
    Posts
  • #38885

    dragonslaya
    Participant

    My team and I, I currently working on rts type style game more based like LoL. Ive been here before asking questions. I would like to be pointed in the right direction of how to export the nav mesh data of my level maps and so I can create my own pathfinding system on server side so my npc creatures can path and server can send proper data back to clients.

    I’m using unity 5.1 and I’m using smartfox server 2x for my backend. I understand the nav mesh data is huge and exporting it will be tedious, but I’m not sure any other way to do the pathfinding on server to send to clients. I would be greatly appreciated to be pushed in the right direction.

    #38890

    Sigil
    Keymaster

    Well, as it goes, the Navigation Mesh data isn’t as large as it seems. So this all depends on what you need on your server. If you are using a headless version of Unity and RAIN on your server, you can directly recreate our Navigation Meshes and path find on them. If you are using your own custom solution, and just need the polygon data from the Navigation Mesh, there are ways of getting that as well.

    First one: The NavMeshPathGraph has a byte[] Serialize() and void Deserialize(byte[] aData) set of functions to handle encoding the Navigation Mesh Data when saving. If you want to manually serialize, send the data to your server, and then deserialize, this would be the way to do it. This assumes you are using Unity and the RAIN Navigation Mesh on your server.

    Second one: Each NavMeshPathGraph is a set of vertices, and a number of polygons and edges that reference those vertices. The NavMeshPathGraph exposes a Vertices property, which returns a read only set of Vector3s that you can do with as you please. In addition to that, it exposes a Size property, and a GetNode property to allow you to fetch any polygon or edge in the graph.

    Before I go write up an example, which one of these do you need to do?

    #38903

    dragonslaya
    Participant

    we will be doing the 2nd option. We wont be using a unity version at all on our server. Greatly appreciate the help.

    #38906

    Sigil
    Keymaster

    I will post up an example a little later today, breaking down the different nodes in the Navigation Mesh Graph.

    #38907

    dragonslaya
    Participant

    Thanks. Just to elaborate on what we want to do. Our server is smartfox server which backend is all java code. We want to be able to basically create our own update pathfinding on server and update clients as needed whenever the npc is within aoi range of the player.

    A) create our own pathfinding system using the data provided by rain from the nav mesh of the map.

    We need to be able to hook into the rain dll and use that to use the already built in functions of rain to do it on server. I assumed that rain is heavily dependable on unity so that 2nd option wouldn’t be possible.

    If it is possible and you could show us how to do it that be a lot easier but if not we are more then happy to code our own small scale pathfinding system for server using the data provided by rain’s nav mesh off our levels.

    #38910

    Sigil
    Keymaster

    Hmmm, as long as the Unity assemblies are present, I imagine you can create a navigation mesh and call many of its functions without having any trouble. Outside of the rigs, most of RAIN is designed to work outside of Unity. We are dependent on things like Unity’s Quaternions and Vectors but we don’t rely on the Update messages (outside the rigs at least) or any deep portion of Unity. Maybe I’m not thinking clearly though, I’ll have to test that a bit.

    Anyhow, here is the example as promised:

    using RAIN.Navigation.NavMesh;
    using System.Collections.Generic;
    using UnityEngine;
    public class EnumerateNavMesh : MonoBehaviour
    {
        public void Enumerate()
        {
            NavMeshRig tRig = gameObject.GetComponent<NavMeshRig>();
            NavMeshPathGraph tGraph = tRig.NavMesh.Graph;
            // This is the transform of the navigation mesh, usually the GameObject it is attached to
            Transform tGraphMount = tRig.NavMesh.MountPoint;
            // These vertices will be relative to the mount point mentioned above
            List<Vector3> tVertices = new List<Vector3>(tGraph.Vertices);
            for (int i = 0; i < tGraph.Size; i++)
            {
                // Every node in the graph is either a NavMeshPoly
                if (tGraph.GetNode(i) is NavMeshPoly)
                {
                    NavMeshPoly tPoly = (NavMeshPoly)tGraph.GetNode(i);
                    // These are the points of the convex poly that the Navigation Mesh uses
                    int[] tPolyBorder = new int[tPoly.ContourCount];
                    for (int j = 0; j < tPolyBorder.Length; j++)
                        tPolyBorder[j] = tPoly.GetContour(j);
                    // These are the interior triangles of those polys, not really necessary right now
                    // (you can retriangulate pretty easy) but may be necessary in the future
                    int[] tPolyTriangles = new int[tPoly.TriangleCount];
                    for (int j = 0; j < tPoly.TriangleCount; j++)
                        tPolyTriangles[j] = tPoly.GetTriangle(j);
                }
                // Or a NavMeshEdge
                else if (tGraph.GetNode(i) is NavMeshEdge)
                {
                    NavMeshEdge tEdge = (NavMeshEdge)tGraph.GetNode(i);
                    // The edges aren't necessarily useful, as you have pretty much everything you need
                    // from the polys
                    int[] tEdgePoints = new int[2]
                    {
                        tEdge.IndexOne,
                        tEdge.IndexTwo
                    };
                    // I didn't show this in the previous loop, but you can tell what polys you are
                    // connected to with any edge, and with any poly you can get a list of edges as well
                    NavMeshPoly[] tPolys = new NavMeshPoly[tEdge.PolyCount];
                    for (int j = 0; j < tEdge.PolyCount; j++)
                        tPolys[j] =     tEdge.GetPolyNode(j);
                }
            }
        }
    }
    #39280

    dragonslaya
    Participant

    I’m sorry I been extreme busy with game and work and real life stuff. I finally got to working on trying to create an export for rain navigation mesh info. I decided to make something more visual and or create spawning points on any terrain using rains nav mesh. What I have created so far seems to be good. I haven’t test it but I’m here going to post what I have got so far. Id like some info as to if I’m going in a good direction and or if I’m even getting the right info I need to spawn at a real good position where object wont be stuck not moving.

    first file is the MonoBehaviour script you need to attach it to the same object the rains navigation mesh rig is on.

    #if DEBUG
    #region Using Statements
    using System.Collections.Generic;
    using RAIN.Navigation.NavMesh;
    using UnityEngine;
    #endregion
    namespace Assets.Scripts.Game_Scripts.Rain_Helpers
    {
        public class RainNavMeshExport : MonoBehaviour
        {
            #region Variables
            [SerializeField] private int _numberOfSpawns;
            [HideInInspector] public List<Vector3> SpawnLocations;
            #endregion
            public void ExportInfo()
            { }
            public void CreateSpawns()
            {
                var tRig = GetComponent<NavMeshRig>();
                var tGraph = tRig.NavMesh.Graph;
                SpawnLocations.Clear();
                for (var i = 0; i < _numberOfSpawns; i++)
                {
                    var rndNode = Random.Range(0, tGraph.Size);
                    // Every node in the graph is either a NavMeshPoly
                    if (tGraph.GetNode(rndNode) is NavMeshPoly)
                    {
                        var tPoly = (NavMeshPoly)tGraph.GetNode(rndNode);
                        if(tPoly.Unwalkable || SpawnLocations.Contains(tPoly.Position)) continue;
                        SpawnLocations.Add(tPoly.Position);
                        //// These are the points of the convex poly that the Navigation Mesh uses
                        //var tPolyBorder = new int[tPoly.ContourCount];
                        //for (var j = 0; j < tPolyBorder.Length; j++)
                        //    tPolyBorder[j] = tPoly.GetContour(j);
                        //// These are the interior triangles of those polys, not really necessary right now
                        //// (you can retriangulate pretty easy) but may be necessary in the future
                        //var tPolyTriangles = new int[tPoly.TriangleCount];
                        //for (var j = 0; j < tPoly.TriangleCount; j++)
                        //    tPolyTriangles[j] = tPoly.GetTriangle(j);
                    }
                    // Or a NavMeshEdge
                    ////else if (tGraph.GetNode(i) is NavMeshEdge)
                    ////{
                    ////    var tEdge = (NavMeshEdge)tGraph.GetNode(i);
                    ////    The edges aren't necessarily useful, as you have pretty much everything you need
                    ////     from the polys
                    ////    var tEdgePoints = new int[2]
                    ////    {
                    ////    tEdge.IndexOne,
                    ////    tEdge.IndexTwo
                    ////    };
                    ////    I didn't show this in the previous loop, but you can tell what polys you are
                    ////     connected to with any edge, and with any poly you can get a list of edges as well
                    ////    var tPolys = new NavMeshPoly[tEdge.PolyCount];
                    ////    for (var j = 0; j < tEdge.PolyCount; j++)
                    ////        tPolys[j] = tEdge.GetPolyNode(j);
                    ////}
                }
            }
        }
    }
    #endif

    the 2nd file is a custom editor script to control creating spawn points and then exporting them. I haven’t implemented exporting the info. Shouldn’t be hard I am just storing the vector3 points of each arrow.

    #if DEBUG
    #region Using Statements
    using Assets.Scripts.Game_Scripts.Rain_Helpers;
    using RAIN.Navigation.NavMesh;
    using UnityEditor;
    using UnityEngine;
    #endregion
    namespace Assets.Scripts.Generic_Scripts.Editor 
    {
        [CustomEditor(typeof(RainNavMeshExport))]
        public class SpawnLocationGizmos : UnityEditor.Editor
        {
            #region Variables
            //[SerializeField] private GameObject _spawnFlagPrefab;
            private RainNavMeshExport _tRig;
            #endregion
            #region Unity Methods
            public void OnSceneGUI()
            {
                _tRig = (RainNavMeshExport) target;
                Handles.BeginGUI();
                {
                    GUILayout.BeginArea(new Rect(20, 20, 150, 50), "Box");
                    {
                        if (GUILayout.Button("Create Spawns"))
                            _tRig.CreateSpawns();
                        if (GUILayout.Button("Export Locations"))
                        {
                            _tRig.ExportInfo();
                        }
                    }
                    GUILayout.EndArea();
                }
                Handles.EndGUI();
                if (_tRig.SpawnLocations.Count <= 0) return;
                Handles.color = Color.red;
                for (var i = 0; i < _tRig.SpawnLocations.Count; i++)
                {
                    Handles.ArrowCap(i, _tRig.SpawnLocations[i], Quaternion.LookRotation(Vector3.down), 50);
                }
            }
            #endregion
        }
    }
    #endif
    • This reply was modified 10 months, 1 week ago by  dragonslaya.
    #39286

    Sigil
    Keymaster

    Seems fine for the most part. The one thing I’d note is that technically your CreateSpawns function could find no spawn points, as it is possible that every choice comes up as a NavMeshEdge (which gets skipped).

    What you may want to do instead is create a new list containing only NavMeshPolys and then choose a random index and remove it from that list.

Viewing 8 posts - 1 through 8 (of 8 total)

You must be logged in to reply to this topic.