News Forums RAIN General Discussion and Troubleshooting walk waypoint network (beginner)

This topic contains 22 replies, has 4 voices, and was last updated by  prime 1 year ago.

Viewing 8 posts - 16 through 23 (of 23 total)
  • Author
    Posts
  • #35310

    prime
    Keymaster

    @tyoc213 - I don’t think you would want to add AI-specific information to objects in the environment. Instead, I think AI can track that information individually and use it as required. That can easily be done with a small mode to the code presented in this thread. However, I’m not sure how much good a “visited” flag does in this case. You will eventually run into situations where every connected node has been visited.

    #35434

    Arno1975
    Participant

    Prime, I keep struggeling where to set the priorWaypoint. I think i need an extra step to store the correct data.
    When the Ai is walking towards waypoint 1,
    when it arrives, it stores the waypoint in holdingWaypoint,
    then it sets its new waypoint, waypoint 2 and walks towards waypoint 2,
    when it arrives at waypoint 2; priorWaypoint=holdingWaypoint (waypoint 1) and holdingWaypoint becomes waypoint 2, it sets it’s new target waypoint 3, now priorWaypoint is the waypoint it came from.

    It think i have the logic correct, but I’m not sure where to put it in the code.

    #35449

    prime
    Keymaster

    Here’s an updated version of the code. Given that I’ve messed this up a couple of times, I can’t say this is totally correct yet. It should be close though. I changed what we were previously calling “lastWaypoint” to be called “currentWaypoint”. Then I used the “lastWaypoint” variable to hold the prior waypoint whenever we choose a new current.

    using UnityEngine;
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using RAIN.Action;
    using RAIN.Core;
    using RAIN.Representation;
    using RAIN.Motion;
    using RAIN.Navigation;
    using RAIN.Navigation.Graph;
    using RAIN.Navigation.Waypoints;
    [RAINAction("Choose Next Waypoint")]
    public class ChooseWaypoint : RAINAction
    {
        public Expression WaypointNetwork = new Expression(); //either the name of the network or a variable containing a network
        public Expression MoveTargetVariable = new Expression(); //the variable you want to use for the output move target
        private MoveLookTarget moveTarget = new MoveLookTarget();
    	private int currentWaypoint = -1;
        private int lastWaypoint = -1;
        private WaypointSet lastWaypointSet = null;
        public override ActionResult Execute(AI ai)
        {
    	    //Fail if a valid move target variable was not passed in
            if (!MoveTargetVariable.IsValid || !MoveTargetVariable.IsVariable)
                return ActionResult.FAILURE;
    		//Get the waypoint set we want to use.  See the function below.
    		//Fail if no matching waypoint set is found
            WaypointSet waypointSet = GetWaypointSetFromExpression(ai);
            if (waypointSet == null)
                return ActionResult.FAILURE;
    		//If our waypoint set has changed, reset our last/current waypoints
            if (waypointSet != lastWaypointSet)
            {
                lastWaypoint = -1;
    			currentWaypoint = -1;
                lastWaypointSet = waypointSet;
            }
    		//If we don't have a current waypoint, then just grab the nearest one and use it
            if (currentWaypoint == -1)
            {
                currentWaypoint = waypointSet.GetClosestWaypointIndex(ai.Kinematic.Position);
                if (currentWaypoint < 0)
                    return ActionResult.FAILURE;
                moveTarget.VectorTarget = waypointSet.Waypoints[currentWaypoint].position;
                moveTarget.CloseEnoughDistance = Mathf.Max(waypointSet.Waypoints[currentWaypoint].range, ai.Motor.CloseEnoughDistance);
                if (!ai.Motor.IsAt(moveTarget))
                {
                    ai.WorkingMemory.SetItem<MoveLookTarget>(MoveTargetVariable.VariableName, moveTarget);
                    return ActionResult.SUCCESS;
                }
            }
    		//Check all connections to our current waypoint.  Create a list of valid connections, excluding
    		//those that go to our lastWaypoint.  Choose randomly from that list
    		NavigationGraphNode tNode = waypointSet.Graph.GetNode(currentWaypoint);
            if (tNode.OutEdgeCount > 0)
            {
                List<int> tConnectedNodes = new List<int>();
                for (int k = 0; k < tNode.OutEdgeCount; k++)
                {
                  int tIndex = ((VectorPathNode)tNode.EdgeOut(k).ToNode).NodeIndex;
                  if ((tIndex != lastWaypoint) && (!tConnectedNodes.Contains(tIndex)))
                    tConnectedNodes.Add(tIndex);
                }
    			lastWaypoint = currentWaypoint;
                if (tConnectedNodes.Count == 0)
                  currentWaypoint = ((VectorPathNode)tNode.EdgeOut(0).ToNode).NodeIndex;
                else
                  currentWaypoint = tConnectedNodes[UnityEngine.Random.Range(0, tConnectedNodes.Count)];
            }
    		//Set the moveTarget based on our choice
            moveTarget.VectorTarget = waypointSet.Waypoints[currentWaypoint].position;
            moveTarget.CloseEnoughDistance = Mathf.Max(waypointSet.Waypoints[currentWaypoint].range, ai.Motor.CloseEnoughDistance);
            ai.WorkingMemory.SetItem<MoveLookTarget>(MoveTargetVariable.VariableName, moveTarget);
            return ActionResult.SUCCESS;
        }
        private WaypointSet GetWaypointSetFromExpression(AI ai)
        {
            WaypointSet waypointSet = null;
            if (WaypointNetwork != null && WaypointNetwork.IsValid)
            {
                if (WaypointNetwork.IsVariable)
                {
                    string varName = WaypointNetwork.VariableName;
                    if (ai.WorkingMemory.ItemExists(varName))
                    {
                        Type t = ai.WorkingMemory.GetItemType(varName);
                        if (t == typeof(WaypointRig) || t.IsSubclassOf(typeof(WaypointRig)))
                        {
                            WaypointRig wgComp = ai.WorkingMemory.GetItem<WaypointRig>(varName);
                            if (wgComp != null)
                                waypointSet = wgComp.WaypointSet;
                        }
                        else if (t == typeof(WaypointSet) || t.IsSubclassOf(typeof(WaypointSet)))
                        {
                            waypointSet = ai.WorkingMemory.GetItem<WaypointSet>(varName);
                        }
                        else if (t == typeof(GameObject))
                        {
                            GameObject go = ai.WorkingMemory.GetItem<GameObject>(varName);
                            if (go != null)
                            {
                                WaypointRig wgComp = go.GetComponentInChildren<WaypointRig>();
                                if (wgComp != null)
                                    waypointSet = wgComp.WaypointSet;
                            }
                        }
                        else
                        {
                            string setName = ai.WorkingMemory.GetItem<string>(varName);
                            if (!string.IsNullOrEmpty(setName))
                                waypointSet = NavigationManager.Instance.GetWaypointSet(setName);
                        }
                    }
                    else
                    {
                        if (!string.IsNullOrEmpty(varName))
                            waypointSet = NavigationManager.Instance.GetWaypointSet(varName);
                    }
                }
                else if (WaypointNetwork.IsConstant)
                {
                    waypointSet = NavigationManager.Instance.GetWaypointSet(WaypointNetwork.Evaluate<string>(0, ai.WorkingMemory));
                }
            }
            return waypointSet;
        }
    }
    • This reply was modified 1 year, 4 months ago by  prime.
    #35462

    Arno1975
    Participant

    Prime,

    This is great, I’ve got the same result that what i started with, using the Unity pathfinding. But now I got the great options of Rain, to continue building my AI.
    My next step will be AI to AI affoidence, but i will figure that one out on my own, or is it better to wait for the next update. I read that you guys are working on that?

    Thanks for all your effort en time…

    #35894

    Arno1975
    Participant

    Prime,
    When the AI arrives at a deadend it just turns around and goes to the previus waypoint.
    Is there a possibility to destroy the object when it arrives at a dead end. That would be great.
    I could then use the same script for spawning AI.

    #35895

    prime
    Keymaster

    Sure. You are looking for 2 conditions (you can see them both in the code):

    if (tNode.OutEdgeCount > 0)

    and

    if (tConnectedNodes.Count == 0)

    If either of those happens, it means you don’t have an unvisited node to go to. That’s where you would clean things up.

    #38191

    christougher
    Participant

    This works exactly like I needed. Waypoints appear to be selected randomly from all connected waypoints to the current WP. I didn’t need to exlude the prior WP so the second version of the code worked great for me. Thanks!

    I do get the following yellow warnings from unity though:

    Assets/AI/Actions/RainRandomWaypoint.cs(61,96): warning CS0618: `RAIN.Navigation.Waypoints.Waypoint.range’ is obsolete: `Use Range instead’

    Assets/AI/Actions/RainRandomWaypoint.cs(60,79): warning CS0618: `RAIN.Navigation.Waypoints.Waypoint.position’ is obsolete: `Use LocalPosition or Position instead’

    Assets/AI/Actions/RainRandomWaypoint.cs(45,104): warning CS0618: `RAIN.Navigation.Waypoints.Waypoint.range’ is obsolete: `Use Range instead’

    Assets/AI/Actions/RainRandomWaypoint.cs(44,87): warning CS0618: `RAIN.Navigation.Waypoints.Waypoint.position’ is obsolete: `Use LocalPosition or Position instead’

    Assets/AI/Actions/RainRandomWaypoint.cs(40,52): warning CS0618: `RAIN.Navigation.Waypoints.WaypointSet.GetClosestWaypointIndex(UnityEngine.Vector3)’ is obsolete: `Use GetClosestWaypoint instead’

    #38203

    prime
    Keymaster

    Yes, you should update your code based on the information in the warnings. RAIN has changed a bit from when the original was posted.

Viewing 8 posts - 16 through 23 (of 23 total)

You must be logged in to reply to this topic.