Stwórz NPC, który będzie podążał za graczem w Unity

Postacie niezależne lub NPC to postacie, które nie są kontrolowane przez gracza, a zamiast tego są kontrolowane przez skrypty lub AI.

Najczęstszym zadaniem, jakie muszą wykonać NPC-e, jest podążanie lub gonienie Gracza.

W tym samouczku pokażę, jak stworzyć NPC, który podąża za graczem w Unity.

Krok 1: Utwórz kontroler odtwarzacza

Stworzymy prosty kontroler gracza, abyśmy mogli chodzić i testować NPC:

  • Utwórz nowy obiekt GameObject („GameObject” -> 'Create Empty') i nadaj mu nazwę "Player"
  • Utwórz nową kapsułę („GameObject” -> '3D Object' -> 'Capsule'), przenieś ją do obiektu gracza i zmień jej położenie na (0, 1, 0)
  • Usuń komponent Capsule Collider z kapsuły
  • Przesuń główną kamerę wewnątrz obiektu gracza i zmień jej położenie na (0, 1.64, 0)
  • Utwórz nowy skrypt, nazwij go 'SC_CharacterController' i wklej w nim poniższy kod:

'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);
        }
    }
}
  • Dołącz skrypt 'SC_CharacterController' do obiektu gracza i przypisz podrzędną kamerę główną do zmiennej kamery gracza
  • Zauważysz, że automatycznie dodał kolejny komponent o nazwie Character Controller, zmieniając jego środkową pozycję na (0, 1, 0)

Krok 2: Utwórz NPC

Aby utworzyć NPC, wykonaj poniższe czynności:

  • Utwórz nowy obiekt GameObject i nazwij go „NPC”
  • Utwórz nową kapsułę, przenieś ją do obiektu NPC i zmień jej położenie na (0, 1, 0)
  • Utwórz nowy materiał i nadaj mu nazwę "npc_material"
  • Zmień kolor npc_material na czerwony
  • Przypisz npc_material do kapsuły wewnątrz obiektu NPC (w ten sposób możemy odróżnić NPC od Gracza)

Zanim przejdziemy dalej, musimy upiec NavMesh w naszej scenie.

NavMesh oznacza "Navigation Mesh" i jest używany do wyszukiwania ścieżki, aby umożliwić NPC poruszanie się po poziomie bez wpadania na przeszkody.

Aby upiec NavMesh, wykonaj poniższe czynności:

  • Oznacz każdy statyczny obiekt na scenie jako statyczny nawigacji

  • Przejdź do okna nawigacji („Okno” -> 'AI' -> 'Navigation'), wybierz zakładkę Pieczenie, a następnie kliknij Piecz

Po upieczeniu NavMesh powinien wyglądać mniej więcej tak:

Unity 3D NavMesh Bake

Teraz możemy przejść do programowania ruchu NPC:

  • Dołącz komponent 'NavMesh Agent' do obiektu NPC
  • Utwórz nowy skrypt i nadaj mu nazwę 'SC_NPCFollow'
  • Dołącz skrypt 'SC_NPCFollow' do obiektu NPC
  • Otwórz skrypt 'SC_NPCFollow'

Najpierw zaczynamy od dodania przestrzeni nazw UnityEngine.AI na początku skryptu:

using UnityEngine.AI;

Następnie definiujemy niezbędne zmienne:

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

W 'void Start()' zaczynamy od podłączenia komponentu NavMesh Agent do tego obiektu:

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

Na koniec w 'void Update()' instruujemy Agenta NavMesh, aby podążał za Graczem:

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

Oto ostateczny skrypt '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;
    }
}

Naprawianie niektórych problemów:

Problem 1: Po naciśnięciu przycisku Play kapsuła NPC unosi się nad ziemią:

Rozwiązanie: Zmień zmienną Base Offset w Agencie NavMesh na wartość ujemną (w moim przypadku jest to -0,08)

Problem 2: NPC podchodzi zbyt blisko, gdy podąża za Graczem:

Rozwiązanie: Zmień odległość zatrzymania w agencie NavMesh na wyższą wartość (w moim przypadku ustawiłem ją na 5)

NPC jest już gotowy, przetestujmy go:

Sharp Coder Odtwarzacz wideo

Wszystko działa zgodnie z oczekiwaniami, NPC podąża teraz za Graczem i zatrzymuje się w ustalonej odległości.