Створіть NPC, який слідує за гравцем в Unity

Неігрові персонажі або NPC — це персонажі, якими не керує гравець-людина, а натомість ними керують сценарії або AI.

Найпоширенішим завданням, яке мають виконувати NPC, є слідувати або переслідувати Гравця.

У цьому підручнику я покажу, як створити NPC, який буде слідувати за гравцем у Unity.

Крок 1: Створіть контролер програвача

Ми створимо простий контролер гравця, щоб ми могли ходити та тестувати NPC:

  • Створіть новий GameObject ('GameObject' -> 'Create Empty') і назвіть його "Player"
  • Створіть нову капсулу ('GameObject' -> '3D Object' -> 'Capsule'), перемістіть її всередину об'єкта гравця та змініть її положення на (0, 1, 0)
  • Видаліть компонент Capsule Collider з капсули
  • Перемістіть головну камеру всередину об’єкта гравця та змініть її положення на (0, 1,64, 0)
  • Створіть новий сценарій, назвіть його 'SC_CharacterController' і вставте в нього наведений нижче код:

'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);
        }
    }
}
  • Прикріпіть сценарій 'SC_CharacterController' до об’єкта Player і призначте дочірню основну камеру змінній Player Camera
  • Ви помітите, що він автоматично додав ще один компонент під назвою «Контролер символів», змінивши його центральне положення на (0, 1, 0)

Крок 2: Створіть NPC

Щоб створити NPC, виконайте наведені нижче дії.

  • Створіть новий GameObject і назвіть його "NPC"
  • Створіть нову капсулу, перемістіть її всередину об’єкта NPC і змініть її положення на (0, 1, 0)
  • Створіть новий матеріал і назвіть його "npc_material"
  • Змініть колір npc_material на червоний
  • Призначте npc_material для капсули всередині об’єкта NPC (це лише для того, щоб ми могли відрізнити NPC від гравця)

Перш ніж продовжити, нам потрібно запекти NavMesh у нашій сцені.

NavMesh розшифровується як "Navigation Mesh" і використовується для пошуку шляху, щоб дозволити NPC переміщатися рівнем, не натикаючись на перешкоди.

Щоб запекти NavMesh, виконайте наведені нижче дії.

  • Позначте кожен статичний об’єкт у сцені як навігаційний статичний

  • Перейдіть до вікна навігації («Вікно» -> 'AI' -> 'Navigation'), виберіть вкладку «Випікати», а потім натисніть «Випікати».

Після того, як NavMesh запікається, він має виглядати приблизно так:

Unity 3D NavMesh Bake

Тепер ми можемо переходити до програмування руху NPC:

  • Прикріпіть компонент 'NavMesh Agent' до об’єкта NPC
  • Створіть новий сценарій і назвіть його 'SC_NPCFollow'
  • Прикріпіть сценарій 'SC_NPCFollow' до об’єкта NPC
  • Відкрийте скрипт 'SC_NPCFollow'

Спочатку ми починаємо з додавання простору імен UnityEngine.AI на початку сценарію:

using UnityEngine.AI;

Потім визначаємо необхідні змінні:

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

У 'void Start()' ми починаємо з отримання компонента NavMesh Agent, приєднаного до цього об’єкта:

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

Нарешті, у 'void Update()' ми наказуємо агенту NavMesh слідувати за гравцем:

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

Ось остаточний сценарій '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;
    }
}

Виправлення деяких проблем:

Проблема 1: Після натискання «Відтворити» капсула NPC зависає над землею:

Рішення: Змініть змінну Base Offset в NavMesh Agent на від’ємне значення (у моєму випадку це -0,08)

Проблема 2: NPC підходить занадто близько, коли йде за гравцем:

Рішення: Змініть дистанцію зупинки в NavMesh Agent на вищу величину (у моєму випадку я встановив її на 5)

Тепер NPC готовий, давайте перевіримо його:

Sharp Coder Відеоплеєр

Усе працює належним чином, NPC тепер слідує за гравцем і зупиняється на заданій відстані.

Рекомендовані статті
Впровадження ШІ ворога в Unity
Як створити FPS із підтримкою AI в Unity
Unity Додайте ворогів у 2D-платформер
Робота з NavMeshAgent в Unity
Огляд пакета Unity Asset Store Package - Zombie AI System
Як створити AI оленя в Unity
Система діалогу для єдності