Créer un PNJ qui suit le joueur dans Unity

Les personnages non-joueurs ou PNJ sont les personnages qui ne sont pas contrôlés par un joueur humain mais qui sont plutôt contrôlés par les scripts ou par AI.

La tâche la plus courante que les PNJ doivent accomplir est de suivre ou de poursuivre le joueur.

Dans ce tutoriel, je vais montrer comment créer un PNJ qui suit le joueur en Unity.

Étape 1: Créer le contrôleur de lecteur

Nous allons créer un simple contrôleur de joueur, afin de pouvoir nous promener et tester le PNJ:

  • Créez un nouveau GameObject ('GameObject' -> 'Create Empty') et nommez-le "Player"
  • Créez une nouvelle capsule ('GameObject' -> '3D Object' -> 'Capsule'), déplacez-la à l'intérieur de Player Object et changez sa position en (0, 1, 0)
  • Supprimer le composant Capsule Collider d'une capsule
  • Déplacez la caméra principale à l'intérieur de l'objet joueur et changez sa position en (0, 1,64, 0).
  • Créez un nouveau script, nommez-le 'SC_CharacterController' puis collez le code ci-dessous à l'intérieur:

'SC_CharacterController.cs'

using UnityEngine;

[RequireComponent(typeof(CharacterController))]

public class SC_CharacterController : MonoBehaviour
{
    public float speed = 7.5f;
    public float jumpSpeed = 8.0f;
    public float gravity = 20.0f;
    public Camera playerCamera;
    public float lookSpeed = 2.0f;
    public float lookXLimit = 45.0f;

    CharacterController characterController;
    Vector3 moveDirection = Vector3.zero;
    Vector2 rotation = Vector2.zero;

    [HideInInspector]
    public bool canMove = true;

    void Start()
    {
        characterController = GetComponent<CharacterController>();
        rotation.y = transform.eulerAngles.y;
    }

    void Update()
    {
        if (characterController.isGrounded)
        {
            // We are grounded, so recalculate move direction based on axes
            Vector3 forward = transform.TransformDirection(Vector3.forward);
            Vector3 right = transform.TransformDirection(Vector3.right);
            float curSpeedX = speed * Input.GetAxis("Vertical");
            float curSpeedY = speed * Input.GetAxis("Horizontal");
            moveDirection = (forward * curSpeedX) + (right * curSpeedY);

            if (Input.GetButton("Jump"))
            {
                moveDirection.y = jumpSpeed;
            }
        }

        // Apply gravity. Gravity is multiplied by deltaTime twice (once here, and once below
        // when the moveDirection is multiplied by deltaTime). This is because gravity should be applied
        // as an acceleration (ms^-2)
        moveDirection.y -= gravity * Time.deltaTime;

        // Move the controller
        characterController.Move(moveDirection * Time.deltaTime);

        // Player and Camera rotation
        if (canMove)
        {
            rotation.y += Input.GetAxis("Mouse X") * lookSpeed;
            rotation.x += -Input.GetAxis("Mouse Y") * lookSpeed;
            rotation.x = Mathf.Clamp(rotation.x, -lookXLimit, lookXLimit);
            playerCamera.transform.localRotation = Quaternion.Euler(rotation.x, 0, 0);
            transform.eulerAngles = new Vector2(0, rotation.y);
        }
    }
}
  • Attachez le script 'SC_CharacterController' à l'objet joueur et attribuez une caméra principale enfant à une variable de caméra joueur.
  • Vous remarquerez qu'il a automatiquement ajouté un autre composant appelé Character Controller, changeant sa position centrale en (0, 1, 0).

Étape 2: Créer le PNJ

Pour créer un PNJ, suivez les étapes ci-dessous:

  • Créez un nouveau GameObject et nommez-le "NPC"
  • Créez une nouvelle capsule, déplacez-la dans l'objet NPC et changez sa position en (0, 1, 0).
  • Créez un nouveau matériau et nommez-le "npc_material"
  • Changer la couleur de npc_material en rouge
  • Attribuez npc_material à la capsule à l'intérieur de l'objet NPC (c'est juste pour que nous puissions distinguer le PNJ du joueur)

Avant de continuer, nous devons intégrer le NavMesh dans notre scène.

NavMesh signifie "Navigation Mesh" et est utilisé dans la recherche de chemin pour permettre aux PNJ de naviguer dans le niveau sans se heurter à des obstacles.

Pour préparer le NavMesh, suivez les étapes ci-dessous:

  • Marquez chaque objet statique de la scène comme statique de navigation

  • Accédez à la fenêtre de navigation (« Fenêtre » -> 'AI' -> 'Navigation'), sélectionnez l'onglet Bake, puis cliquez sur Bake.

Une fois le NavMesh cuit, il devrait ressembler à ceci:

Cuisson Unity 3D NavMesh

Passons maintenant à la programmation du mouvement des PNJ:

  • Attachez le composant 'NavMesh Agent' à l'objet NPC
  • Créez un nouveau script et nommez-le 'SC_NPCFollow'
  • Attachez le script 'SC_NPCFollow' à l'objet PNJ
  • Ouvrez le script 'SC_NPCFollow'

Tout d’abord, nous commençons par ajouter un espace de noms UnityEngine.AI au début du script:

using UnityEngine.AI;

Ensuite nous définissons les variables nécessaires:

    //Transform that NPC has to follow
    public Transform transformToFollow;
    //NavMesh Agent variable
    NavMeshAgent agent;

Dans le 'void Start()', nous commençons par attacher le composant NavMesh Agent à cet objet:

    // Start is called before the first frame update
    void Start()
    {
        agent = GetComponent<NavMeshAgent>();
    }

Enfin, dans le 'void Update()', nous demandons à l'agent NavMesh de suivre le joueur:

    // Update is called once per frame
    void Update()
    {
        //Follow the player
        agent.destination = transformToFollow.position;
    }

Voici le script final 'SC_NPCFollow.cs':

using UnityEngine;
using UnityEngine.AI;

public class SC_NPCFollow : MonoBehaviour
{
    //Transform that NPC has to follow
    public Transform transformToFollow;
    //NavMesh Agent variable
    NavMeshAgent agent;

    // Start is called before the first frame update
    void Start()
    {
        agent = GetComponent<NavMeshAgent>();
    }

    // Update is called once per frame
    void Update()
    {
        //Follow the player
        agent.destination = transformToFollow.position;
    }
}

Correction de quelques problèmes:

Problème 1: Après avoir appuyé sur Play, la capsule du PNJ plane au-dessus du sol:

Solution: Modifiez la variable Base Offset dans NavMesh Agent en une valeur négative (dans mon cas, c'est -0,08)

Problème 2: Le PNJ s'approche trop près lorsqu'il suit le joueur:

Solution: Modifiez la distance d'arrêt dans NavMesh Agent sur une valeur plus élevée (dans mon cas, je l'ai définie sur 5)

Le PNJ est maintenant prêt, testons-le:

Sharp Coder Lecteur vidéo

Tout fonctionne comme prévu, le PNJ suit désormais le joueur et s'arrête à une distance définie.

Articles suggérés
Implémentation de l'IA d'un ennemi dans Unity
Comment créer un FPS avec le support de l'IA dans Unity
Examen du package Unity Asset Store - Zombie AI System
Comment faire une IA d'un cerf dans Unity
Travailler avec NavMeshAgent dans Unity
Unity ajoute des ennemis à une plate-forme 2D
Concept de l'IA dans le développement de jeux