Erstelle einen NPC, der dem Spieler in Einheit folgt
Nicht-Spieler-Charaktere oder NPCs sind Charaktere, die nicht von einem menschlichen Spieler gesteuert werden, sondern von den Skripten oder der KI gesteuert werden.
Die häufigste Aufgabe, die NPCs erfüllen müssen, besteht darin, dem Spieler zu folgen oder ihn zu verfolgen.
In diesem Tutorial zeige ich, wie man einen NPC erstellt, der dem Spieler in Unity folgt.
Schritt 1: Erstellen Sie den Player-Controller
Wir werden einen einfachen Player-Controller erstellen, damit wir herumlaufen und den NPC testen können:
- Erstellen Sie ein neues GameObject („GameObject“ -> 'Create Empty') und benennen Sie es "Player"
- Erstellen Sie eine neue Kapsel („GameObject“ -> '3D Object' -> 'Capsule'), verschieben Sie sie in das Player-Objekt und ändern Sie ihre Position in (0, 1, 0).
- Entfernen Sie die Capsule Collider-Komponente aus einer Kapsel
- Bewegen Sie die Hauptkamera in das Player-Objekt und ändern Sie ihre Position in (0, 1,64, 0).
- Erstellen ein neues Skript, nennen Sie es 'SC_CharacterController' und fügen Sie dann den folgenden Code ein:
'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);
}
}
}
- Hängen Sie das 'SC_CharacterController'-Skript an das Player-Objekt an und weisen Sie einer Player-Kamera-Variablen eine untergeordnete Hauptkamera zu
- Sie werden feststellen, dass automatisch eine weitere Komponente namens „Character Controller“ hinzugefügt und ihre Mittelposition auf (0, 1, 0) geändert wurde.
Schritt 2: Erstelle den NPC
Um einen NPC zu erstellen, führen Sie die folgenden Schritte aus:
- Erstellen Sie ein neues GameObject und nennen Sie es „NPC“.
- Erstellen Sie eine neue Kapsel, verschieben Sie sie in das NPC-Objekt und ändern Sie ihre Position in (0, 1, 0).
- Erstellen Sie ein neues Material und benennen Sie es "npc_material"
- Ändern Sie die Farbe von npc_material in Rot
- Weisen Sie npc_material der Kapsel innerhalb des NPC-Objekts zu (dies dient nur dazu, dass wir NPC vom Spieler unterscheiden können).
Bevor wir fortfahren, müssen wir das NavMesh in unserer Szene backen.
NavMesh steht für "Navigation Mesh" und wird bei der Wegfindung verwendet, um es NPCs zu ermöglichen, durch das Level zu navigieren, ohne auf Hindernisse zu stoßen.
Um das NavMesh zu backen, führen Sie die folgenden Schritte aus:
- Markieren Sie jedes statische Objekt in der Szene als Navigationsstatisch
- Gehen Sie zum Navigationsfenster („Fenster“ -> 'AI' -> 'Navigation'), wählen Sie die Registerkarte „Backen“ und klicken Sie dann auf „Backen“.
Nachdem das NavMesh gebacken wurde, sollte es etwa so aussehen:
Jetzt können wir mit der Programmierung der NPC-Bewegung fortfahren:
- Hängen Sie die 'NavMesh Agent'-Komponente an das NPC-Objekt an
- Erstellen ein neues Skript und benennen Sie es 'SC_NPCFollow'
- Hängen Sie das 'SC_NPCFollow'-Skript an das NPC-Objekt an
- Öffnen Sie das 'SC_NPCFollow'-Skript
Zunächst fügen wir am Anfang des Skripts einen UnityEngine.AI-Namespace hinzu:
using UnityEngine.AI;
Dann definieren wir die notwendigen Variablen:
//Transform that NPC has to follow
public Transform transformToFollow;
//NavMesh Agent variable
NavMeshAgent agent;
Im 'void Start()' beginnen wir damit, die NavMesh-Agent-Komponente an dieses Objekt anzuhängen:
// Start is called before the first frame update
void Start()
{
agent = GetComponent<NavMeshAgent>();
}
Schließlich weisen wir im 'void Update()' den NavMesh-Agenten an, dem Spieler zu folgen:
// Update is called once per frame
void Update()
{
//Follow the player
agent.destination = transformToFollow.position;
}
Hier ist das endgültige 'SC_NPCFollow.cs'-Skript:
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;
}
}
Behebung einiger Probleme:
Problem 1: Nach dem Drücken von „Play“ schwebt die NPC-Kapsel über dem Boden:
Lösung: Ändern Sie die Base Offset-Variable im NavMesh Agent auf einen negativen Wert (in meinem Fall ist es -0,08).
Problem 2: Der NPC kommt dem Spieler zu nahe, wenn er ihm folgt:
Lösung: Ändern Sie den Bremsweg im NavMesh Agent auf einen höheren Wert (in meinem Fall habe ich ihn auf 5 gesetzt)
Der NPC ist nun bereit, testen wir ihn:
Alles funktioniert wie erwartet, der NPC folgt nun dem Spieler und stoppt in einer festgelegten Entfernung.