News Forums RAIN Sample Projects, How To, and Code Creating & assigning BT at runtime

This topic contains 1 reply, has 1 voice, and was last updated by  ainoodle 1 month, 3 weeks ago.

Viewing 2 posts - 1 through 2 (of 2 total)
  • Author
    Posts
  • #40330

    ainoodle
    Participant

    Hello everyone, going to be honest here I’ve just started properly using RAIN for a current project and I’ve got to say, very impressed. Although, I’m a bit stumped on how you go about creating (if it’s possible) a BT at runtime. I’ve seen another post that mentions it can be done via three methods, and I decided to go for the purely scripted route.

    So as a noobie basic example, I’ve got something like this:

    // Get your AI rig to assign the tree to
    AIRig aiRig = child.GetComponentInChildren<AIRig> ();
    // Create a new node (waypoint for example)
    BTWaypointNode wpNode = new BTWaypointNode()
    { 
        waypointSetVariable = ExpressionParser.Parse("Waypoint Route"),
        waypointActionType = BTWaypointNode.WaypointActionType.PATROL,
        traverseType = BTWaypointNode.WaypointTraverseType.PINGPONG,
        traverseOrder = BTWaypointNode.WaypointTraverseOrder.FORWARD,
        moveTargetVariable = "waypointTarget"
    };
    // Grab your mind
    BasicMind myMind = ((BasicMind)aiRig.AI.Mind);
    // Assign the created node as its root
    myMind.BehaviorRoot = wpNode;
    // Profit?
    // ...

    It seems that the assignment works, as in, it’s not thrown any errors at me just yet. But does anything else need to be done such as kick-starting the behaviour tree or the AI in to actually running it?

    One more thing and not sure if it’s related, but if you create a BT dynamically, should it appear in the behaviour editor list? I wasn’t sure if it was the case, since that’s an editor-based area that probably isn’t aware of such things.

    Hope this makes sense, sorry if it doesn’t as I’m still just picking things up.

    Many thanks in advance!

    #40331

    ainoodle
    Participant

    Hello again,
    Well it would seem (and thanks to seeing another post: Changing AI Motor At Runtime), that I wasn’t quite getting it right. I’m not 100% sure on whether one needs to have the serialization parts in there, as I’m not sure what they do, but the rest makes sense give or take.

    Basically I’ve integrated RAIN with DunGen, now this allows you to create multiple prefabs of rooms and craft a dungeon from it automatically. In each room, it has a set of waypoints, and potential npcs that spawn. These are where we dynamically load in our behaviour trees, each one has knowledge of the set of waypoints belonging to that room, and uses them to generate that tree.

    The main bulk of the code happens below (it should be more or less right):

    // This is called as soon as the dungeon has been created
    void HandlerMethod (DunGen.DungeonGenerator generator, DunGen.GenerationStatus status)
    {
        // Cheap and cheerful way to get the very top of the room (this could be improved)
        Transform parentTransform = transform.parent.transform;
        // Get the parent that holds your created waypoint game objects
        wpParent = parentTransform.FindChild ("StaticWaypoints").gameObject;
        // I know, not ideal.
        if (wpParent != null) {
            // Some method that generates a unique ID for the route set
            string guid = "route" + GetUniqueIdentifier(true);
            // Creates a new route for the AI to reference to (this is now unique to each room)
            GameObject route = new GameObject(guid);
            route.transform.position = Vector3.zero;
            // Assign to a cache (namely for tidiness)
            route.transform.parent = cacheParent.transform;
            // Attach waypoint rig
            RAIN.Navigation.Waypoints.WaypointRig waypointRig = route.AddComponent<RAIN.Navigation.Waypoints.WaypointRig>();
            // Set the type to a route
            waypointRig.WaypointSet.SetType = RAIN.Navigation.Waypoints.WaypointSet.WaypointSetType.Route;
            // Get all the waypoints you can find (assumes in the right order)
            foreach(Transform sub in wpParent.transform)
            {
                // Instantiate a new waypoint
                RAIN.Navigation.Waypoints.Waypoint wp = new RAIN.Navigation.Waypoints.Waypoint();
                // Set it to the position of the waypoint gameobject (referenced earlier)
                wp.Position = new Vector3 (sub.position.x, sub.position.y, sub.position.z);
                // And add to the route list
                waypointRig.WaypointSet.AddWaypoint(wp);
            }
            // Now you've got your waypoints set up, find the npc(s) you want to register
            npcTest = parentTransform.FindChild("NPEs");
            if (npcTest != null) {
                waypointRig.Serialize();
                // Set up your waypoint node to use
                RAIN.BehaviorTrees.BTWaypointNode tRoot = new RAIN.BehaviorTrees.BTWaypointNode()
                {
                    waypointSetVariable = RAIN.Representation.ExpressionParser.Parse(guid),
                    waypointActionType = RAIN.BehaviorTrees.BTWaypointNode.WaypointActionType.PATROL,
                    traverseType = RAIN.BehaviorTrees.BTWaypointNode.WaypointTraverseType.PINGPONG,
                    traverseOrder = RAIN.BehaviorTrees.BTWaypointNode.WaypointTraverseOrder.FORWARD,
                    moveTargetVariable = "waypointTarget" // Dynamic this thing?
                };
                // Just repeat once done (could use onSuccess, etc)
                tRoot.RepeatUntilState = RAINAction.ActionResult.RUNNING;
                // Make sure you add an action to move the entity
                tRoot.AddChild(new RAIN.BehaviorTrees.Actions.MoveAction()
                {
                    moveTargetExpression = RAIN.Representation.ExpressionParser.Parse("waypointTarget")
                });
                // Search your npc for the actual 'ai rig' on the entity
                foreach (Transform child in npcTest) {
                   AIRig aiRig = child.GetComponentInChildren<AIRig> ();
                   BasicMind myMind = ((BasicMind)aiRig.AI.Mind);
                   if (aiRig) {
                        // set all of the above to the mind of the NPC
                        RAIN.Minds.BasicMind basicMind = aiRig.AI.Mind as RAIN.Minds.BasicMind;
                        basicMind.BehaviorRoot = tRoot;
                        // Why do this?
                        aiRig.Serialize();
                   }
                }
            }
        }
    }

    I hope it comes in useful for some, if nothing else it’s been a learning adventure. And obviously any questions / comments, please fire away. I’m no pro at C#, but know my way around a void…

    Cheers

    • This reply was modified 1 month, 3 weeks ago by  ainoodle.
Viewing 2 posts - 1 through 2 (of 2 total)

You must be logged in to reply to this topic.