Update a List Of WayPoints After An Event

KO_Games

Member
In my game, I have an AI character that patrols a list of waypoints using the patrol with A* in the behavior tree movement pack. In the start of my game, the AI can only access certain areas of a house. Once the player opens up doors to certain areas of the house I then want the AI to be able to now patrol those new areas as well. The goal is to have a list of waypoints that the AI Patrols at the start of the level. Once the player then opens a door, I would like a new waypoint to be added to the list of patrol points.

Since the player can open doors in any order I was thinking the best way to handle this would be using events. Once a door for a certain area is opened I could send off an event that would update the patrol waypoint list by adding the new waypoint to the list of patrol waypoints. I think I know how to execute the event part, but I don't know how to add new waypoints to the patrol list of waypoints. What would be the best way to accomplish something like this?

Also, is there a way I can easily store all of the waypoints I want to add once a certain event takes place inside Behaviour tree?

Thanks!
 
What would be the best way to accomplish something like this?
If your using the movement pack the waypoints is a SharedGameobjectList so I would have a separate script which listens for your door event and then updates the SharedGameObjectList. You can do this by accessing the Value property.

Also, is there a way I can easily store all of the waypoints I want to add once a certain event takes place inside Behaviour tree?

In this case I think that it would be easiest to just control outside of the behavior tree using a separate script.
 
Thanks for the response Justin. I started to work on creating a separate list outside of behaviour tree like you mentioned, but the part that I get stuck at is I don't know how to send the updated list to behaviour tree to then feed into the patrol waypoint list? Maybe I'm going about this the wrong way. Here is the external script I have so far:

Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BehaviorDesigner.Runtime;

public class UpdatePatrolWaypointList : MonoBehaviour
{
    public SharedGameObjectList waypointsStartingList;
    public GameObject waypointToAdd1;

    private List<GameObject> waypointList;

    private void Start()
    {
        waypointList = waypointsStartingList.Value;
    }

    private void OnEnable()
    {
        //Subscribe to OnDoorOpened event += UpdateWayPointList;
    }

    private void OnDisable()
    {
        //Unsubscribe to OnDoorOpened event -= UpdateWayPointList;
    }

    private void UpdateWayPointList()
    {
        waypointList.Add(waypointToAdd1);
        //How do I then use this updated list in behaviour tree?
    }
}
 
Instead of having the SharedGameObjectList within the MonoBehaviour, you should use GetVariable. Take a look at this page:

 
Thanks Justin. That helped point me in the right direction, and I got it figured out. The only thing I'm having an issue with Patrol now is my AI doesn't wait at the waypoints for the specified duration set in behaviour tree. I have 5 seconds as the input for the waypoint pause duration. For some reason, the AI only waits at the first waypoint for 5 seconds and then when the AI reaches the other waypoints the AI just moves on to the next waypoint as soon as it arrives at the waypoint. It does not wait the 5 seconds. I think the issue is somewhere here in the Patrol code:

C#:
public override TaskStatus OnUpdate()
        {
            if (HasArrived())
            {
                if (waypointReachedTime == -waypointPauseDuration.Value)
                {
                    waypointReachedTime = Time.time;
                }
                // wait the required duration before switching waypoints.
                if (waypointReachedTime + waypointPauseDuration.Value <= Time.time)
 
Hi Justin. I figured out the problem. The issue was that I had forgotten that I had changed HasArrived bool in the IAstarAIMovement script due to another issue I had had earlier with the seek task returning as true when the agent had not finished seeking (as noted by other people in the community here) I used the suggestions by the community to fix the seeking issue by doing the following in the IAstarAIMovement script:
C#:
protected override void Stop()
        {
            agent.isStopped = true;
            agent.destination = Vector3.positiveInfinity;//transform.position;
            //agent.canMove = false;
        }

        protected override bool HasArrived()
        {
            return agent.reachedDestination || (agent.remainingDistance <= arriveDistance.Value && !agent.isStopped);
        }

The issue with this fix is the second part highlighted below then causes the HasArrived bool to return true even though the agent has not yet arrived at the waypoint, which then causes the agent to not wait at the waypoints.
C#:
(agent.remainingDistance <= arriveDistance.Value && !agent.isStopped)

The way I fixed this without breaking the seek task was to put the following check in the patrol task (which I could have just replaced with instead of the HasArrived bool, but I wanted to remind myself for the future why I made the change).
C#:
if (HasArrived())
            {
                //Added this if statement below because HasArrived bool above doesn't work for patrol because the second option returns as true always or too often.
                //Can't remove the second part of the HasArrived condition though because it will mess up the seek function.
                if (agent.reachedDestination)
                {                       
                    if (waypointReachedTime == -waypointPauseDuration.Value)
                    {
                        waypointReachedTime = Time.time;
                    }

                    // wait the required duration before switching waypoints.
                    if (waypointReachedTime + waypointPauseDuration.Value <= Time.time)
                    {

Let me know if you think there is a cleaner way to handle this.
 
That looks like it should work for now. With A* I have never figured out a good HasArrived condition that works for every use case. I plan on doing an update to the add-ons and with that update I need to really sit down and bang out all of the cases.
 
Top