قم بإنشاء شخصية غير قابلة للعب (NPC) تتبع اللاعب في Unity
الشخصيات التي ليست لاعبين أو NPCs هي الشخصيات التي لا يتحكم فيها لاعب بشري ويتم التحكم فيها بدلاً من ذلك بواسطة البرامج النصية أو AI.
المهمة الأكثر شيوعًا التي يتعين على الشخصيات غير القابلة للعب القيام بها هي متابعة اللاعب أو مطاردته.
في هذا البرنامج التعليمي، سأوضح كيفية إنشاء شخصية غير قابلة للعب (NPC) تتبع اللاعب في Unity.
الخطوة 1: إنشاء وحدة تحكم المشغل
سنقوم بإنشاء وحدة تحكم بسيطة للمشغل، حتى نتمكن من التجول واختبار الشخصية غير القابلة للعب:
- قم بإنشاء GameObject جديد ("GameObject" -> 'Create Empty') وقم بتسميته "Player"
- قم بإنشاء كبسولة جديدة ('GameObject' -> '3D Object' -> 'Capsule')، وحركها داخل Player Object، وقم بتغيير موضعها إلى (0، 1، 0)
- قم بإزالة مكون مصادم الكبسولة من الكبسولة
- حرك الكاميرا الرئيسية داخل كائن المشغل وقم بتغيير موضعها إلى (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"
- أنشئ كبسولة جديدة، وحركها داخل الكائن غير القابل للعب، وقم بتغيير موضعه إلى (0، 1، 0)
- قم بإنشاء مادة جديدة وقم بتسميتها "npc_material"
- قم بتغيير لون npc_material إلى اللون الأحمر
- قم بتعيين npc_material إلى الكبسولة داخل كائن NPC (وهذا فقط حتى نتمكن من التمييز بين NPC واللاعب)
قبل المتابعة، نحتاج إلى خبز NavMesh في مشهدنا.
يرمز NavMesh إلى "Navigation Mesh" ويستخدم في تحديد المسار للسماح للشخصيات غير القابلة للعب بالتنقل في المستوى دون الاصطدام بالعوائق.
لخبز 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: بعد الضغط على زر التشغيل، تحوم كبسولة NPC فوق الأرض:
الحل: قم بتغيير متغير Base Offset في NavMesh Agent إلى قيمة سالبة (في حالتي هو -0.08)
المشكلة 2: يقترب NPC كثيرًا عند متابعة اللاعب:
الحل: قم بتغيير مسافة التوقف في NavMesh Agent إلى قيمة أعلى (في حالتي قمت بتعيينها على 5)
NPC جاهز الآن، فلنختبره:
كل شيء يعمل كما هو متوقع، والشخصية غير القابلة للعب تتبع اللاعب الآن وتتوقف عند مسافة محددة.