Search Unity

NavMesh Third Person??

Discussion in 'Navigation' started by chainsawpenguin, Nov 24, 2018.

  1. chainsawpenguin

    chainsawpenguin

    Joined:
    Sep 28, 2014
    Posts:
    107
    I feel like I'm missing something fundamental here, so bear with me:

    I'm trying to create a third-person control for my player using a navmeshagent. However, when I use the code below, I'm confused because the Vector3.forward (and also Vector3.right) do not update when the navmesh is turned.

    In other words, pressing "up" always moves my player towards the top of the map, regardless of my facing. Vector3.forward is defined when I start the scene, and never changes.

    What am I missing here?



    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.AI;
    [RequireComponent(typeof(NavMeshAgent))]
    public class PlayerControl_NavMesh : MonoBehaviour {
    private Vector3 myGoal;
    public NavMeshAgent myAgent;
    public Animator myAnimator;
    void Start()
    {
    Cursor.visible = false;
    myGoal = transform.position;
    myAgent = GetComponent<NavMeshAgent>();
    myAnimator = GetComponent<Animator>();
    }
    void Update ()
    {
    myGoal = transform.position
    + Vector3.forward * Input.GetAxis("Vertical")
    + Vector3.right * Input.GetAxis("Horizontal");
    myAgent.destination = myGoal;
    myAnimator.SetFloat("mySpeed", myAgent.velocity.magnitude);
    }
    }
     
  2. chainsawpenguin

    chainsawpenguin

    Joined:
    Sep 28, 2014
    Posts:
    107
    UPDATE: How to use a NavMesh with typical Third-Person Control

    You have to apply the Vector3.forward and Vector3.right to the current rotation!!

    I feel like I've asked this question about fifteen different ways, and I think I've received zero responses because I wasn't being clear enough in my question.

    Below is the code that works correctly, giving you a normal character movement around a NavMesh, without using a Character Controller or other weirdness!!



    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.AI;
    [RequireComponent(typeof(NavMeshAgent))]
    public class PlayerControl_NavMesh : MonoBehaviour {
    private Vector3 myGoal;
    public NavMeshAgent myAgent;
    public Animator myAnimator;
    public Camera myCamera;
    void Start()
    {
    Cursor.visible = false;
    myGoal = transform.position;
    myAgent = GetComponent<NavMeshAgent>();
    myAnimator = GetComponent<Animator>();
    }
    void Update ()
    {
    myGoal = transform.position
    + transform.rotation * Vector3.forward * Input.GetAxis("Vertical")
    + transform.rotation * Vector3.right * Input.GetAxis("Horizontal");
    myAgent.destination = myGoal;
    myAnimator.SetFloat("mySpeed", myAgent.velocity.magnitude);
    }
    }
     
  3. the_0dium

    the_0dium

    Joined:
    Nov 29, 2018
    Posts:
    15
    Isn't using navmesh for player control a weirdness ?
     
    leftshoe18 likes this.
  4. Yandalf

    Yandalf

    Joined:
    Feb 11, 2014
    Posts:
    491
    Yeah, I agree here that using a NavMeshAgent for direct control approach is probably not a good idea.
    NavMesh would make more sens if you'd have a "click to move to" system, like in Diablo.
    With what you're doing here you could just apply the input directly to your gameObject instead of first relaying it through the NavMesh, or even wire your input to the application of forces on your rigidbody.
    Take a look at the standard third person controller examples Unity has.
     
    tf007 and leftshoe18 like this.
  5. leftshoe18

    leftshoe18

    Joined:
    Jul 29, 2017
    Posts:
    61
    As others have pointed out using NavMesh for something like this is kinda strange.

    But a quick tip:
    Instead of doing
    Vector3.forward * transform.rotation
    and
    Vector3.right * transform.rotation
    you can just use
    transform.forward
    and
    transform.right
    instead.
     
    Thura-Soe and timmccune like this.
  6. chainsawpenguin

    chainsawpenguin

    Joined:
    Sep 28, 2014
    Posts:
    107
    The reason I wanted to use a NavMeshAgent for the player is so that:
    • The player and the NPCs can never get into a position where one can't reach a location the other can't, because they're constrained to the same navmesh.
    • The functions available to the NavMeshAgent that affect the NPCs can be directly applied to the player without any additional code.
    • We don't have to set up a gazillion colliders to box in the player, since he's constrained to the NavMesh.

    It's precisely for all of these reasons, and more, that click-to-move games use navmesh agents for players (as correctly pointed out above). It just seems insane to me that there's NOT a good way to do this, given all of the inherent benefits (and when combined with a Cinemachine freelook camera, you have the exactly the functionality I'm looking for).

    And the transform.forward and transform.right don't work, because the navmesh doesn't actually change which direction is forward when the model turns, which is why I did it the hack-y way I did it.

    I may be missing something fundamental, but it just seems like a question that at least one person might have solved in the past in an elegant way.
     
  7. Yandalf

    Yandalf

    Joined:
    Feb 11, 2014
    Posts:
    491
    Yeah, that elegant way is not using navmeshes and being careful with your level geometry to avoid the situations which you're trying to solve for with said navmesh.
    It's such a roundabout way of translating your input into a destination and then have your "directly" controlled player character figure out a short path to said destination and move towards it with Unity's Agent Movement code that you can't modify outside of some variables, and judging from the hacks you're attempting here I'd say it's overcomplicating things with tools that weren't designed for the task.
    Oh well, seems like you got it to work somehow. Here's hoping it pays off.