צור NPC שעוקב אחרי הנגן באחדות
דמויות שאינן שחקנים או NPCs הן הדמויות שאינן נשלטות על ידי שחקן אנושי ובמקום זאת נשלטות על ידי התסריטים או AI.
המשימה הנפוצה ביותר שאנשי NPC צריכים לעשות, היא לעקוב אחר הנגן או לרדוף אחריו.
במדריך זה, אני אראה כיצד ליצור NPC שעוקב אחר הנגן ב-Unity.
שלב 1: צור את בקר הנגן
ניצור בקר נגן פשוט, כדי שנוכל להסתובב ולבדוק את ה-NPC:
- צור GameObject חדש ('GameObject' -> 'Create Empty') ושם לו "Player"
- צור קפסולה חדשה ('GameObject' -> '3D Object' -> 'Capsule'), הזז אותה בתוך אובייקט Player, ושנה את מיקומה ל- (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' לאובייקט הנגן והקצה מצלמה ראשית למשתנה של מצלמה של נגן
- אתה תבחין שהוא הוסיף אוטומטית רכיב נוסף בשם Character Controller, משנה את המיקום המרכזי שלו ל- (0, 1, 0)
שלב 2: צור את ה-NPC
כדי ליצור NPC, בצע את השלבים הבאים:
- צור GameObject חדש וקרא לו "NPC"
- צור קפסולה חדשה, הזז אותה בתוך אובייקט NPC ושנה את מיקומה ל- (0, 1, 0)
- צור חומר חדש ושם לו "npc_material"
- שנה את הצבע של npc_material לאדום
- הקצה npc_material לקפסולה בתוך אובייקט NPC (זה רק כדי שנוכל להבחין בין NPC לנגן)
לפני שנמשיך, עלינו לאפות את NavMesh בסצנה שלנו.
NavMesh מייצג "Navigation Mesh" ומשמש באיתור נתיבים כדי לאפשר ל-NPCs לנווט ברמה מבלי להיתקל במכשולים.
כדי לאפות את NavMesh, בצע את השלבים הבאים:
- סמן כל אובייקט סטטי בסצנה כסטטי ניווט
- עבור אל חלון הניווט ('חלון' -> 'AI' -> 'Navigation'), בחר בכרטיסייה אפייה ולאחר מכן לחץ על אפייה
לאחר אפיית ה-NavMesh, הוא אמור להיראות בערך כך:
כעת נוכל לעבור לתכנות של תנועת 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: לאחר לחיצה על Play, קפסולת ה-NPC מרחפת מעל הקרקע:
פתרון: שנה את המשתנה Base Offset ב-NavMesh Agent לערך שלילי (במקרה שלי זה -0.08)
בעיה 2: ה-NPC מתקרב מדי כאשר עוקב אחר הנגן:
פתרון: שנה את מרחק העצירה ב-NavMesh Agent לערך גבוה יותר (במקרה שלי הגדרתי אותו ל-5)
ה-NPC מוכן כעת, בואו נבדוק אותו:
הכל עובד כמצופה, ה-NPC עוקב כעת אחרי הנגן ועוצר במרחק מוגדר.