البطل
جزء من قسم هندسة الألعاب في Unity في رحلة Unity على Coddy. الدرس 41 من 50.
يبني هذا الفصل لعبة Arena Survivor، وهي اللعبة الأخيرة في هذه الرحلة. تندفع موجات الأعداء إلى ساحة محاطة بالجدران، وتقاتلهم بسيفك: أعداء مشاة يتجهون نحوك، وكرات تنتظر ثم تندفع. تترك الموجة المهزومة تعزيزًا، وتعرض واجهة HUD صحتك والموجة، وعندما تنفد صحتك تنتهي الجولة ويُحفَظ أفضل أداء لك. تستخدم اللعبة أدوات هذا القسم حيثما كان ذلك مناسبًا: فئة Enemy مجردة لها نوعان، وواجهة IDamageable لكل ما يمكن أن يتلقى الضرر، والموجات كأصل ScriptableObject، والتقاطات عبر واجهة، وواجهة HUD لا تستمع إلا إلى أحداث C#، وحفظ بصيغة JSON. توجد السكربتات الاثنا عشر كلها في المشروع منذ البداية. لم يُكتب الكود بعد إلا لفئة Hero، ويضيف كل درس المزيد.
يضرب سيف البطل ما يقع أمامه، لذا يحتاج التأرجح إلى اختبار يحدد ما إذا كان الهدف «أمامي». تضرب Vector3.Dot(a, b) الأجزاء المتناظرة من متجهين ثم تجمعها: a.x * b.x + a.y * b.y + a.z * b.z. وبالنسبة إلى اتجاهين طول كل منهما 1، تكون النتيجة جيب تمام الزاوية بينهما: 1 عندما يشيران إلى الاتجاه نفسه، و0.866 عند 30 درجة، و0.707 عند 45، و0 عند الزوايا القائمة، و-1 عندما يشيران إلى اتجاهين متعاكسين. لذلك تصبح عبارة «ضمن 30 درجة من اتجاه نظري» هي «قيمة الضرب النقطي لا تقل عن 0.866»، من دون الحاجة إلى حساب زاوية. يطلق روبوت الحراسة هذا الإنذار عندما يكون اللاعب ضمن 10 وحدات وداخل مجال رؤيته البالغ 30 درجة:
public Transform player;
public float range = 10f;
void Update()
{
Vector3 toPlayer = player.position - transform.position;
toPlayer.y = 0f;
bool near = toPlayer.magnitude <= range;
bool inView = Vector3.Dot(transform.forward, toPlayer.normalized) >= 0.866f;
if (near && inView)
{
Debug.Log("Alarm!");
}
}يجب أن يكون طول كلا الاتجاهين 1. يتحقق ذلك دائمًا في transform.forward، لكن طول toPlayer يساوي المسافة، لذا يُطبَّع أولًا؛ وإلا فإن اللاعب الذي يبعد ضعف المسافة سيعطي ضعف قيمة الضرب النقطي. تُضبط قيمة y فيه على 0 قبل ذلك، لذا يُحتسب اللاعب الموجود على ممر مرتفع بحسب موقعه على الخريطة، لا بحسب ارتفاعه. تحدد إشارة القيمة ما إذا كان الاتجاه أماميًا أم خلفيًا: فقيمة الضرب النقطي الأكبر من 0 تعني أي موضع في النصف الأمامي، والأقل من 0 تعني أي موضع خلفك.
التحدي
متوسطابدأ Arena Survivor بسيف البطل. كُتبت الحركة: يحرّك الإجراء Move البطل باستخدام SimpleMove ويديره لمواجهة الاتجاه الذي يتحرك فيه. تقف حوله خمس دمى تدريب تحمل الوسم Enemy. يضبط Inspector قيمة reach إلى (2) وقيمة swingCooldown إلى (0.5) في Hero، وكذلك الضربة التي تظهر أثناء التأرجح.
- يؤدي الضغط على Space أو النقر بزر الفأرة الأيسر إلى التأرجح، مرة واحدة كل
swingCooldownثانية كحد أقصى: لا يفعل الضغط قبل انتهاء فترة الانتظار شيئًا. اقرأ المفاتيح باستخدامKeyboard.currentوMouse.current، واستدعِSwing(). - في
Swing()، بعد إظهار الضربة، دمّر كل كائن يحمل الوسمEnemyويقع ضمنreachوأمام البطل. يعني «ضمن المدى» أي مصادم تجدهPhysics.OverlapSphereحول البطل بنصف قطرreach. ويعني «أمام» أن يكون الجداء النقطي بين اتجاه البطل الأمامي والاتجاه نحو الكائن على امتداد الأرض 0.5 على الأقل: حتى 60 درجة إلى أي من الجانبين.
اترك البرامج النصية الأخرى كما هي. اضغط تشغيل، وامشِ نحو الدمى وتأرجح، ثم اضغط تحقّق.
جرّب بنفسك
using System.Collections;
using UnityEngine;
using UnityEngine.InputSystem;
public class Hero : MonoBehaviour
{
[SerializeField] private float speed = 5f;
[SerializeField] private float reach = 2f;
[SerializeField] private float swingCooldown = 0.5f;
[SerializeField] private GameObject slash;
private CharacterController controller;
private InputAction moveAction;
void Start()
{
controller = GetComponent<CharacterController>();
moveAction = InputSystem.actions.FindAction("Move");
}
void Update()
{
Vector2 input = moveAction.ReadValue<Vector2>();
Vector3 move = new Vector3(input.x, 0f, input.y);
controller.SimpleMove(move * speed);
if (move != Vector3.zero)
{
transform.rotation = Quaternion.LookRotation(move);
}
// الضغط على Space أو النقر بزر الفأرة الأيسر ينفّذ ضربة، بمعدل لا يتجاوز مرة واحدة كل swingCooldown ثانية
}
void Swing()
{
StartCoroutine(ShowSlash());
// دمّر كل ما يحمل الوسم Enemy ويقع ضمن مدى الوصول وأمام البطل
}
IEnumerator ShowSlash()
{
slash.SetActive(true);
yield return new WaitForSeconds(0.1f);
slash.SetActive(false);
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس هندسة الألعاب في Unity
1المكوّنات لا التسلسلات الهرمية
مكوّنات صغيرةسكربت أساسي للعدومكوّنات مجرّدةتعمل المكوّنات معًامراجعة: برج دفاعي معياري4البيانات المتسلسلة
الأصناف القابلة للتسلسلالقوائم في Inspectorالتعدادات في Inspectorمراجعة: جدول الغنائم10مشروع: الناجي في الساحة
البطلأنواع الأعداء