NavMeshAgent Not Stopping Before Hitting Interactable Object

,

Hello,

I’m making an RPG with point-and-click movement like the one in GameDev.TV’s RPG course on Udemy. The player movement code is mostly the same as it is in the course, but for some reason, one part is not working in my project. When the player clicks on an interactable object, like a crate that can be looted, they should run up to it until they are 2 distance units away then stop:



BugSnippet 3

As you can see, this portion of the code is identical to that written in the course. However, my character just runs straight through the object and then executes the interaction animation inside. Has anyone run into this?

Edit: I’m using 2021.1.17f1

It might help to see the entire InteractWithObject script.
Rather than pasting a screenshot, try copying and pasting the script. You can then select the entire script and press the </> button to turn it into code, or you can type ``` (the backwards quote next to the 1 on the keyboard three times) on it’s own line… example
```
public class Example
{
}
```
becomes

public class Example
{
}
1 Like

Thank you for responding! Here’s the script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using HorrorRPG.Controller;
using HorrorRPG.Movement;
using HorrorRPG.Core;

namespace HorrorRPG.Interactable 
{
    public class InteractWithObject : MonoBehaviour, IAction 
    {
        Transform target;
        float weaponRange = 2f;

        private void Update() {
            if (target == null) return; 
            if (distanceLessThanWeaponRange() == false) {
                GetComponent<MovePlayer>().MovePlayerToClick(target.position);
            }
            else {
                GetComponent<MovePlayer>().Cancel();
                Debug.Log("YOU ARE IN THE WEAPON RANGE");
                InteractionSequence();
            }
        }

        void InteractionSequence() {
            Debug.Log("You are interacting with the object");
            GetComponent<Animator>().SetTrigger("interact");
        }

        public void Interact(InteractionTarget interactionTarget) {
            GetComponent<ActionScheduler>().StartAction(this);
            target = interactionTarget.transform;
        }

        bool distanceLessThanWeaponRange() {
            return Vector3.Distance(transform.position, target.position) <= weaponRange;
        }

       
        public void Cancel() {
            target = null;
        }
    }   
}

I cleaned it up a bit (remove the spaces between the lines).

Everything looks right, so we may need to look for a different explanation.

The next link in the chain will be to look at the PlayerController.cs

1 Like

Thanks for taking a look through. This is my player controller script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using HorrorRPG.Movement;
using HorrorRPG.Interactable;

namespace HorrorRPG.Controller {
    public class CharacterController : MonoBehaviour
    {
        // Update is called once per frame
        void Update()
        {
            if (InteractableObject()) return;
            if (MovementRay()) return;
        }

        private static Ray GenerateRay() {
            return Camera.main.ScreenPointToRay(Input.mousePosition);
        }

        
        bool MovementRay() {
            RaycastHit hit;
            bool rayHit = Physics.Raycast(GenerateRay(), out hit);
            if (rayHit == true)
            {
                if (Input.GetMouseButton(0))
                {
                    GetComponent<MovePlayer>().MoveToNonInteractable(hit.point);
                }
                return true;
            }
            return false;
        }
    
        bool InteractableObject() 
        {
            RaycastHit[] hits = Physics.RaycastAll(GenerateRay());
            foreach (RaycastHit hit in hits) {
                InteractionTarget target = hit.transform.GetComponent<InteractionTarget>();
                if (target == null) continue;
                if (Input.GetMouseButtonDown(0)) {
                    GetComponent<InteractWithObject>().Interact(target);
                }
                return true;
            }
            return false;
        }
    }
}

That looks basically right as well…

The next place to look is in the NavMeshAgent. Check to see that the Stopping Distance is 0 and Auto Braking is checked.

Both of those settings have been in place. Inexplicably, I logged on and the error is suddenly different. Now, instead of running inside the object, the player lays down on the ground and spins around it. I thought it was some new combat and health scripts that I attached after your response, but I removed both and the bug persisted. The only animation I have that causes the player to lay on the ground is the death animation, but that is only triggered through the health script, so since I removed that script I don’t think that is being triggered.

image

What’s the size on that capsule… it looks to have a radius bigger than 2 compared to the size of the character…

Do you have a Rigidbody on your character? If so, make sure that it is Kinematic, and make sure to lock the axes. That’s the only reason I could see that the character would flop onto it’s side.

print(target.GetComponent<Renderer>().bounds.size) got me (1.8, 3.7, 1.8). If I understand correctly that means a radius of 1.8, correct?

Also, my character does not have a Rigidbody. I had one on originally and it was making the movement incredibly choppy.

Yes, that would mean the capsule’s radius is 1.8, but… where is the capsule’s origin point?

Since the Renderer is in the root of the target, in order for it to be standing properly on the ground, it’s location would have to be aproximately 1.8 off of the ground. Remember that Vector3.Distance works off of the full distance between the two vectors, based on all three dimensions. This means that your character will need to be virtually in the center of the capsule before it’s distance is less than 2.

Try putting the capsule itself under an empty GameObject, and then making the empty GameObject the target. Adjust the capsule so that the base of the capsule rests on the ground (set it’s local position to 0,1.8,0).

1 Like

That worked! Thank you for all your help on this, that was a tough one. He still runs through the obstacle if I click the terrain on the side opposite to where he’s standing, but I’ll use a NavMeshObstacle component for that.

Much appreciated!

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms