Wait for NavMeshAgent to move to position

Announcements, support questions, and discussion for the Dialogue System.
hidingso
Posts: 26
Joined: Sat Sep 25, 2021 2:07 pm

Wait for NavMeshAgent to move to position

Post by hidingso »

Hi Tony, hope you are having a good day

Is there a way to wait for NavMeshAgent to reach a destination besides some arbitrary delay or custom script?

What I am trying to achieve is something like this.

1. Player talks to NPC.
2. NPC moves to Player and plays an animation.
3. Next dialogue is shown.

Thanks in advance!
User avatar
Tony Li
Posts: 22143
Joined: Thu Jul 18, 2013 1:27 pm

Re: Wait for NavMeshAgent to move to position

Post by Tony Li »

Hi,

You can write a custom sequencer command that sets the NavMeshAgent's destination, waits until the NavMeshAgent reaches the destination, and then calls the Stop() method. If you use that sequencer command in your step 2, it will wait for the command to finish before proceeding to step 3.

Alternatively, you can set the destination some other way, and use the built-in WaitForMessage() sequencer command, such as: WaitForMessage(Arrived)

When the NPC gets to the destination, call Sequencer.Message("Arrived") in C# or use a Dialogue System Trigger set to OnTriggerEnter that has a Play Sequence action. Set the sequence to: SequencerMessage(Arrived)
hidingso
Posts: 26
Joined: Sat Sep 25, 2021 2:07 pm

Re: Wait for NavMeshAgent to move to position

Post by hidingso »

Hi Tony,

I made the custom sequencer script, and it works ALMOST.

Code: Select all

namespace PixelCrushers.DialogueSystem.SequencerCommands
{

    public class SequencerCommandNavMeshDestination : SequencerCommand
    {
        public NavMeshAgent agent = null;
        public Transform destination = null;

        private bool reached = false;

        public void Start()
        {
            destination = GetSubject(0);
            Transform a = GetSubject(1, speaker.transform);

            if (a && destination)
            {
                agent = a.gameObject.GetComponentInChildren<NavMeshAgent>();

                if (agent)
                {
                    reached = false;
                    agent.SetDestination(destination.position);
                    StartCoroutine(TravelToDestination());
                }
                else
                {
                    Debug.LogWarning("No agent found");
                }
            }
            else
            {
                Debug.LogWarning("No destination ar subject found");
            }
        }

        public void Update()
        {
            if (agent && destination)
            {
                if (!agent.pathPending)
                {
                    if (agent.remainingDistance <= agent.stoppingDistance)
                    {
                        if (!agent.hasPath || agent.velocity.sqrMagnitude == 0f)
                        {
                            reached = true;
                        }
                    }
                }
            }
        }

        public IEnumerator TravelToDestination()
        {
            yield return new WaitUntil(() => reached == true);
            Debug.Log("NavMeshAgent reached destination, calling Stop()");
            Stop();
        }

    }

}
The Debug message before Stop() is called correctly, but for some reason, the dialogue does not progress even if I call Stop(). Looking at the dialogue editor, the node which runs the sequence remains green and doesn't go to the next node.

In the sequencer I am just calling "NavMeshDestination(Player, NPC);".
User avatar
Tony Li
Posts: 22143
Joined: Thu Jul 18, 2013 1:27 pm

Re: Wait for NavMeshAgent to move to position

Post by Tony Li »

It looks like you could simplify that code to:

Code: Select all

namespace PixelCrushers.DialogueSystem.SequencerCommands
{

    public class SequencerCommandNavMeshDestination : SequencerCommand
    {
        public NavMeshAgent agent = null;
        public Transform destination = null;

        public void Start()
        {
            destination = GetSubject(0);
            Transform a = GetSubject(1, speaker.transform);

            if (a && destination)
            {
                agent = a.gameObject.GetComponentInChildren<NavMeshAgent>();

                if (agent)
                {
                    agent.SetDestination(destination.position);
                    agent.isStopped = false;
                }
                else
                {
                    Debug.LogWarning("No agent found");
                    Stop();
                }
            }
            else
            {
                Debug.LogWarning("No destination or subject found");
                Stop();
            }            
        }

        public void Update()
        {
            if (agent && destination)
            {
                if (!agent.pathPending)
                {
                    if (agent.remainingDistance <= agent.stoppingDistance)
                    {
                        if (!agent.hasPath || agent.velocity.sqrMagnitude == 0f)
                        {
                            Debug.Log("NavMeshAgent reached destination, calling Stop()");
                            Stop();
                        }
                    }
                }
            }
        }

    }
}
Please give that a try and, if it doesn't fix the issue, temporarily set the Dialogue Manager's Debug Level to Info. This will log additional info to the Console window that might indicate what's going on under the hood.
hidingso
Posts: 26
Joined: Sat Sep 25, 2021 2:07 pm

Re: Wait for NavMeshAgent to move to position

Post by hidingso »

I changed the code, and it works as previously; Stop() is called, but the dialogue doesn't progress.

I checked the debug logs, but nothing out of ordinary popped into my vision.



Here are the logs. 1 and 2 mark the nodes. Node 2 is an empty node only with the sequencer command. After these logs nothing happens, everything is still.
User avatar
Tony Li
Posts: 22143
Joined: Thu Jul 18, 2013 1:27 pm

Re: Wait for NavMeshAgent to move to position

Post by Tony Li »

As a test, what happens if you press Escape? (I'm assuming that the Escape key is still mapped to the Dialogue Manager's Input Settings > Cancel Subtitle Input > Key dropdown. If not, disregard this test.)

Would it be possible for you to send a reproduction project to tony (at) pixelcrushers.com?
hidingso
Posts: 26
Joined: Sat Sep 25, 2021 2:07 pm

Re: Wait for NavMeshAgent to move to position

Post by hidingso »

Pressing Escape (or in this case down arrow since I remapped it) continues the dialogue.

I'll see if I can reproduce the problem in a more sendable project.
User avatar
Tony Li
Posts: 22143
Joined: Thu Jul 18, 2013 1:27 pm

Re: Wait for NavMeshAgent to move to position

Post by Tony Li »

Sounds good.

I just thought to check one more thing. If you remove that sequencer command, does the conversation continue on its own? Let's confirm that the command is what's preventing the conversation from continuing.
hidingso
Posts: 26
Joined: Sat Sep 25, 2021 2:07 pm

Re: Wait for NavMeshAgent to move to position

Post by hidingso »

Interestingly, I could not reproduce the problem on a fresh project (The dialogue continued as intended). I also noticed I was running rather old version of Dialogue System.

I will try to update the main project Dialogue System and see if that fixes the problem.
hidingso
Posts: 26
Joined: Sat Sep 25, 2021 2:07 pm

Re: Wait for NavMeshAgent to move to position

Post by hidingso »

The issue seems to be Continue Button. Right now, on my main project, I have continue button set as "Always". By default this option is "Never".

I cannot change it back to "Never", as it seemingly breaks typewriter and my "press F key to continue dialogue" invisible continue button.

Do I somehow have to call Continue within the custom sequencer script?
Post Reply