News Forums RAIN General Discussion and Troubleshooting Runtime navmesh generation and pathfinding tutorial?

This topic contains 9 replies, has 5 voices, and was last updated by  darkhog 11 months, 3 weeks ago.

Viewing 10 posts - 1 through 10 (of 10 total)
  • Author
    Posts
  • #36234

    darkhog
    Participant

    Hello, it’s that stupid noob once again ;).

    Is there any tutorial on RAIN that focuses on doing AI in dynamic context (user-made or procedural maps)? I can’t find any and my googling only gave me review of (old) version of RAIN and couple unrelated links related to actual rain (the weather one).

    #36236

    prime
    Keymaster

    We haven’t made a tutorial like that ourselves. Anyone else out there?

    #36237

    darkhog
    Participant

    Hm. Maybe you should make one then. Procedural games seems to be all the rage nowadays, so this tutorial would be useful for people who want to make such game. Or game with user-made content.

    I’m, unfortunately, clueless on how to do that myself, otherwise this topic wouldn’t exist. And I don’t think I’m the only one - large amount of mineclones done in Unity I’ve seen were without any AI whatsoever. Even Space Engineers doesn’t have any (didn’t play it for quite some time so it might’ve changed).

    • This reply was modified 1 year, 1 month ago by  darkhog.
    #36305

    grotesque
    Participant

    Hi, I’m also fairly new to RAIN AI and stumbled upon the the same problem and your post here.

    Unfortunately RAIN lacks in bigger code examples, so I gathered some code snippets and a little test project working that might also fits in your case.

    Description:
    - just one object in the scene
    - which has the NavMeshRig and a C# script attached
    - the c# script instatiates the prefabs
    - the player prefab has an blank AIRIG attached
    - the target prefab has an blank Navigation Target Rig attached
    - the parameters for the Rigs are set by the C# script
    - player uses an existing BehaviourTree to find the target
    - player is spawned when the NavMesh creation process is finished

    https://www.dropbox.com/s/k7h431xfnxtjtlg/New%20Unity%20Project%202.zip?dl=0

    C# Code

    using RAIN.Navigation.NavMesh;
    using System.Collections.Generic;
    using System.Collections;
    using UnityEngine;
    using RAIN.Navigation;
    using RAIN.Navigation.Targets;
    using RAIN.Core;
    using RAIN.BehaviorTrees;
    using RAIN.Minds;
    using RAIN.Memory;
    using RAIN;
    public class NavMeshGen : MonoBehaviour
    {
        private int _threadCount = 4;
        NavMeshRig tRig;
        private bool isNavMeshDone = false;
        void Awake()
        {
            //create Plane
            GameObject plane = (GameObject)Instantiate(Resources.Load("prefab/Plane2"));
            plane.transform.position = new Vector3(22, 0, 0);
            //create Plane
            GameObject wall = (GameObject)Instantiate(Resources.Load("prefab/wall"));
            wall.transform.position = new Vector3(10, 0.5f, 0);
            // create target
            GameObject target = (GameObject)Instantiate(Resources.Load("prefab/target2"));
            target.transform.position = new Vector3(22, 1, 6);
            target.gameObject.GetComponentInChildren<NavigationTargetRig>().Target.MountPoint = target.transform;
            target.gameObject.GetComponentInChildren<NavigationTargetRig>().Target.TargetName = "NavTarget";
            // create NavMesh
            tRig = gameObject.GetComponentInChildren<RAIN.Navigation.NavMesh.NavMeshRig>();
            StartCoroutine(GenerateNavmesh());
            // NavMesh ready ???
            StartCoroutine(navMeshCheck());
        }
        void Start()
        {
        }
        // This is just to test the runtime generation
        public void Update()
        {
        }
        // This will regenerate the navigation mesh when called
        IEnumerator GenerateNavmesh()
        {
            // Unregister any navigation mesh we may already have (probably none if you are using this)
            tRig.NavMesh.UnregisterNavigationGraph();
            tRig.NavMesh.Size = 20;
            float startTime = Time.time;
            tRig.NavMesh.StartCreatingContours(tRig, _threadCount);
            while (tRig.NavMesh.Creating)
            {
                tRig.NavMesh.CreateContours();
                yield return new WaitForSeconds(1);
            }
            isNavMeshDone = true;
            float endTime = Time.time;
            Debug.Log("NavMesh generated in " + (endTime - startTime) + "s");
            gameObject.GetComponentInChildren<RAIN.Navigation.NavMesh.NavMeshRig>().NavMesh.RegisterNavigationGraph();
            gameObject.GetComponentInChildren<RAIN.Navigation.NavMesh.NavMeshRig>().Awake();
        }
        IEnumerator navMeshCheck()
        {
            yield return new WaitForSeconds(1);
            if (isNavMeshDone)
            {
                Spawn();
            }
            else { StartCoroutine(navMeshCheck()); }
        }
         private void Spawn()
        {
            // create Player
            GameObject player = (GameObject)Instantiate(Resources.Load("prefab/playergen"));
            player.transform.position = new Vector3(22, 1, -6);
            //BTAsset bTree = ScriptableObject.CreateInstance<BTAsset>();
            // TODO Speed ???
            player.gameObject.GetComponentInChildren<AIRig>().AI.Motor.DefaultSpeed = 10;
             // target
            //player.gameObject.GetComponentInChildren<AIRig>().AI.Motor.MoveTarget.VariableTarget = "NavTarget";
            //player.gameObject.GetComponentInChildren<AIRig>().AI.Motor.MoveTarget.VectorTarget = new Vector3(0, 0, 0);
            //player.gameObject.GetComponentInChildren<AIRig>().AI.Motor.MoveTo(new Vector3(20, 1, 5));
            //player.gameObject.GetComponentInChildren<AIRig>().AI.Motor.Move();
            //player.gameObject.GetComponentInChildren<AIRig>().AI.Motor.MoveTarget.VectorTarget = player.gameObject.GetComponentInChildren<AIRig>().WorkingMemory.GetItem<Vector3>("NavTarget");
             // Create the asset
            // Assign the tree xml, mine was exported from another tree and saved within my project
            BTAsset tCustomAsset = ScriptableObject.CreateInstance<BTAsset>();
            TextAsset xml = Resources.Load("btrees/test2") as TextAsset;
            tCustomAsset.SetTreeData(xml.text);
            tCustomAsset.SetTreeBindings(new string[0] { });
            ((BasicMind)player.gameObject.GetComponentInChildren<AIRig>().AI.Mind).SetBehavior(tCustomAsset, new List<BTAssetBinding>());
        }
    }

    P.S.
    NavMesh creation takes some seconds

    • This reply was modified 1 year, 1 month ago by  grotesque.
    • This reply was modified 1 year, 1 month ago by  grotesque.
    • This reply was modified 1 year, 1 month ago by  grotesque.
    #37757

    darkhog
    Participant

    Sorry for bumping it now, but soon I think I’ll have level editor done and will start to integrate RAIN. However, could you perhaps make example project in Unity, grotesque? I hardly understand how this work so having working example handy would be really helpful.

    //edit: Silly me, noticed dropbox link just now.

    Well, if anyone could make proper tutorial about it, it’d be great. Procedural generation is all the rage now, so having tutorial on how to generate navmesh at runtime would be cool.

    • This reply was modified 11 months, 4 weeks ago by  darkhog.
    #37766

    micuccio
    Participant

    Yes It will be great. And, connecting to another post, It would be the best if could be done with a Playmaker custom action.

    #37771

    prime
    Keymaster

    Quick note: you can now attach NavMeshRigs to objects that are prefabbed. Instantiating the object is all that is necessary - you don’t have to regen the navmesh at runtime anymore (the navmesh will obey the new positioning of the prefab).

    Steps:

    1) Create your object, attach a navmesh, generate the navmesh.
    2) Create a prefab from your object.
    3) Instantiate the prefab at runtime and position it in the scene.

    Any AI that walk over the prefab will correctly use the navmesh.

    #37782

    darkhog
    Participant

    Except game I’m making will use user-generated content for levels. Levels will be put together from many elements that may and will be mixed often in wierd arrangements, so navmesh generation at runtime is needed.

    Terrible ascii-art but will show what I mean.

    At the start of “level” scene, it is purely empty, aside of camera, light, and player character:

                             <CAM
            L
    P

    Then, from level file, certain elements (let’s say “blocks”) are loaded that construct level geometry:

                        __   <CAM
            L          /  \
                       |  |
    P                  \__/
    _________/\_____________________
    |_______/__\___________________|
           /____\

    “Blocks” may and will intersect each others, for the sake of simplicity, let’s just say level is built from primitives.

    At the final step, player start and camera are moved to their proper positions:

                 CAM>   P_   
            L          /  \
                       |  |
                       \__/
    _________/\_____________________
    |_______/__\___________________|
           /____\

    With that sort of setup, generating navmesh at runtime is neccessary, not to mention when your game feature procedural environments.

    • This reply was modified 11 months, 4 weeks ago by  darkhog.
    • This reply was modified 11 months, 4 weeks ago by  darkhog.
    • This reply was modified 11 months, 4 weeks ago by  darkhog.
    • This reply was modified 11 months, 4 weeks ago by  darkhog.
    #37791

    blockcipher
    Participant

    Unless I misread what you are looking for, grotesque posted some code above (specifically in the GenerateNavmesh body) that will do exactly what you want. You would load all your scene assets, make sure they have proper colliders and generate the navmesh. I’ve used code similar (even on spherical worlds, with a bit of code hacking) and know it works and has been in RAIN for a while.

    Are you looking to do this without coding or something like that? Again sorry if I misunderstood what you are trying to accomplish.

    #37801

    darkhog
    Participant

    The main problem with grotesque’s code is that, despite the comments, I don’t understand it. There are two main types of code you’ll encounter, really: Code you understand and code written by someone else.

    So I’m looking for someone who’d write tutorial that would make me understand this, so I can write necessary code myself.

    • This reply was modified 11 months, 3 weeks ago by  darkhog.
Viewing 10 posts - 1 through 10 (of 10 total)

You must be logged in to reply to this topic.