NPC seguir jogador na Unity 3D

Utilizando poucas linhas de código e o componente NavMesh podemos fazer com que um GameObject siga outro.

Em diversos jogos como The Witcher 3: Wild Hunt, Resident Evil Revelations 2, entre muitos outros jogos, acontece de nossos parceiros ou NPCs, seguirem nossos passos, literalmente, e para isso, é necessário um algoritmo que determine o melhor caminho e a distância que eles deve ficar do player.

Vamos entender um pouco como esse processo funciona sem se aprofundar, e mais adiante, você confere a nossa videoaula, ensinando passo a passo de como fazer um objeto seguir o player em um cenário cheio de obstáculos.

Uma malha de navegação, ou NavMesh, é uma estrutura de dados abstrata usada em aplicativos de inteligência artificial para ajudar os agentes a encontrar caminhos em espaços complicados. Fonte https://en.wikipedia.org/wiki/Navigation_mesh

Recomendo fortemente que você leia a documentação oficial da Unity em https://docs.unity3d.com/Manual/nav-BuildingNavMesh.html.

Agora explicando como o processo funciona, basicamente o algoritmo de Inteligência Artificial mapeia todo o cenário na qual a navegação é estática, ou seja, os objetos não vão sair do lugar. O mapeamento utiliza uma série de informações, como o tamanho e largura dos objetos que passarão posteriormente pelo caminho, isso é necessário para computador se o caminho calculado pode ou não ser utilizado.

Após a determinação de todos os fatores, o script de NavMesh pega as vértices da malha e vai fazendo mapeamentos, determinando áreas livres e possivelmente trafegáveis.

 

NPCFollow.cs

using UnityEngine;
using UnityEngine.AI;

[RequireComponent(typeof(NavMeshAgent))]
public class NPCFollow : MonoBehaviour
{
    public float distanciaMinima = 2;
    public Transform alvo;

    private NavMeshAgent navMeshAgent;

    void Start()
    {
        navMeshAgent = GetComponent<NavMeshAgent>();
        navMeshAgent.stoppingDistance = distanciaMinima;
    }

    void Update()
    {
        navMeshAgent.SetDestination(alvo.position);
    }
}

PlayerMove.cs

using UnityEngine;

public class PlayerMove : MonoBehaviour
{
    public float velocity = 10;
    
    void Update()
    {
        Vector3 dir = new Vector3(
            Input.GetAxis("Horizontal"),
            0,
            Input.GetAxis("Vertical")
        ) * velocity;


        transform.Translate(dir * Time.deltaTime, Space.World);
    }
}

Bem, por hoje é isso, até a próxima.