الحلقات التكرارية (Loops): تكرار الأوامر وتوليد الأعداء برمجياً


الحلقات التكرارية (Loops): تكرار الأوامر وتوليد الأعداء برمجياً

في هذا الدرس، سنتعلم كيف تستخدم الحلقات التكرارية لتكرار الأوامر بكفاءة. سنقوم بتطبيق ذلك عملياً لتوليد مجموعة من الأعداء برمجياً في محرك Unity باستخدام C#.

الخطوة 1: فهم أساسيات الحلقات التكرارية (for Loop)

الحلقات التكرارية هي هياكل برمجية تسمح لنا بتنفيذ كتلة من التعليمات عدة مرات. حلقة for هي الأكثر شيوعاً وتستخدم عندما نعرف عدد المرات التي نريد فيها تكرار العملية.

ملاحظة تقنية: تتكون حلقة for من ثلاثة أجزاء رئيسية: تهيئة العداد، شرط الاستمرار، وتحديث العداد.

لنبدأ بمثال بسيط يطبع الأرقام من 0 إلى 4 في نافذة Console:

using UnityEngine;

public class LoopExample : MonoBehaviour
{
    void Start()
    {
        // حلقة for بسيطة لطباعة الأرقام
        for (int i = 0; i < 5; i++) // i: العداد، i < 5: شرط الاستمرار، i++: زيادة العداد
        {
            Debug.Log("الرقم الحالي: " + i); // طباعة قيمة العداد في كل تكرار
        }
    }
}

الخطوة 2: تهيئة الأعداء وتوليدهم في Unity

لتوليد الأعداء، سنحتاج إلى "Prefab" (قالب جاهز للكائن) للعدو. سنفترض أن لديك Prefab باسم "EnemyPrefab" في مجلد Resources أو يمكن سحبه إلى متغير عام. سنستخدم حلقة for لتوليد عدة نسخ من هذا الـ Prefab.

لنقم بتعديل السكربت السابق لإضافة متغير للـ Prefab وتوليد الأعداء:

using UnityEngine;

public class EnemySpawner : MonoBehaviour
{
    public GameObject enemyPrefab; // متغير عام لتخزين Prefab العدو

    void Start()
    {
        int numberOfEnemiesToSpawn = 5; // عدد الأعداء المراد توليدهم

        for (int i = 0; i < numberOfEnemiesToSpawn; i++)
        {
            // توليد نسخة جديدة من Prefab العدو
            GameObject newEnemy = Instantiate(enemyPrefab); // إنشاء كائن جديد من الـ prefab
            newEnemy.name = "Enemy_" + i; // تسمية الكائن الجديد لسهولة التعرف عليه

            // تعيين موقع عشوائي للعدو (مثال بسيط)
            // في تطبيق حقيقي، قد تحتاج إلى حساب مواقع أكثر تعقيدًا
            newEnemy.transform.position = new Vector3(i * 2.0f, 0, 0); // وضع كل عدو بجانب الآخر
            Debug.Log("تم توليد العدو: " + newEnemy.name + " في الموقع: " + newEnemy.transform.position);
        }
    }
}

الخطوة 3: إضافة تنوع وتعديل المواقع

يمكننا جعل توليد الأعداء أكثر ديناميكية باستخدام وظائف عشوائية لتحديد مواقعهم. هذا يضيف لمسة من الواقعية ويجعل كل جولة لعب مختلفة.

ملاحظة تقنية: تستخدم Random.Range() لتوليد أرقام عشوائية. يمكن استخدامها لتحديد المواقع، السرعات، أو أي خصائص أخرى.

لنعدل السكربت لتوليد الأعداء في مواقع عشوائية ضمن نطاق معين:

using UnityEngine;

public class AdvancedEnemySpawner : MonoBehaviour
{
    public GameObject enemyPrefab;
    public int numberOfEnemiesToSpawn = 10; // عدد الأعداء المراد توليدهم
    public float spawnRangeX = 10.0f; // نطاق التوليد على محور X
    public float spawnRangeZ = 10.0f; // نطاق التوليد على محور Z

    void Start()
    {
        for (int i = 0; i < numberOfEnemiesToSpawn; i++)
        {
            // توليد إحداثيات عشوائية للموقع
            float randomX = Random.Range(-spawnRangeX, spawnRangeX); // قيمة عشوائية بين -spawnRangeX و +spawnRangeX
            float randomZ = Random.Range(-spawnRangeZ, spawnRangeZ); // قيمة عشوائية بين -spawnRangeZ و +spawnRangeZ
            Vector3 spawnPosition = new Vector3(randomX, 0, randomZ); // إنشاء متجه الموقع

            GameObject newEnemy = Instantiate(enemyPrefab, spawnPosition, Quaternion.identity); // توليد العدو في الموقع العشوائي
            newEnemy.name = "Enemy_" + i;
            Debug.Log("تم توليد العدو: " + newEnemy.name + " في الموقع: " + spawnPosition);
        }
    }
}

الكود النهائي الكامل

هذا هو الكود الكامل الذي يمكنك لصقه في ملف C# جديد داخل مشروع Unity الخاص بك (مثال: AdvancedEnemySpawner.cs). تذكر أن تربط الـ Prefab الخاص بالعدو بمتغير enemyPrefab في محرر Unity.

using UnityEngine;

public class AdvancedEnemySpawner : MonoBehaviour
{
    // المتغيرات العامة التي يمكن تعديلها من محرر Unity
    public GameObject enemyPrefab; // هنا نربط Prefab العدو الذي نريد توليده
    public int numberOfEnemiesToSpawn = 10; // عدد الأعداء الذين سيتم توليدهم
    public float spawnRangeX = 10.0f; // أقصى مدى للتوليد على محور X (من -X إلى +X)
    public float spawnRangeZ = 10.0f; // أقصى مدى للتوليد على محور Z (من -Z إلى +Z)

    void Start()
    {
        // حلقة for تتكرر بعدد الأعداء المطلوب توليدهم
        for (int i = 0; i < numberOfEnemiesToSpawn; i++)
        {
            // توليد إحداثيات عشوائية للموقع داخل النطاق المحدد
            float randomX = Random.Range(-spawnRangeX, spawnRangeX);
            float randomZ = Random.Range(-spawnRangeZ, spawnRangeZ);
            Vector3 spawnPosition = new Vector3(randomX, 0, randomZ); // إنشاء متجه ثلاثي الأبعاد للموقع

            // توليد نسخة من Prefab العدو في الموقع العشوائي وبدون دوران مبدئي (Quaternion.identity)
            GameObject newEnemy = Instantiate(enemyPrefab, spawnPosition, Quaternion.identity);

            // تسمية الكائن الجديد لسهولة التتبع في Hierarchy
            newEnemy.name = "Enemy_" + i;

            // طباعة رسالة في نافذة Console لتأكيد التوليد والموقع
            Debug.Log("تم توليد العدو: " + newEnemy.name + " في الموقع: " + spawnPosition);
        }
    }
}

النتيجة المتوقعة

عند تشغيل اللعبة في Unity، سيقوم السكربت بتوليد عدد محدد من كائنات "العدو" (وفقاً لقيمة numberOfEnemiesToSpawn) في مواقع عشوائية ضمن نطاق محدد على محوري X و Z. ستظهر كل هذه الكائنات في نافذة Hierarchy، وستطبع رسائل في نافذة Console تؤكد توليد كل عدو وموقعه. على سبيل المثال:

تم توليد العدو: Enemy_0 في الموقع: (-5.2, 0.0, 7.8)
تم توليد العدو: Enemy_1 في الموقع: (3.1, 0.0, -1.5)
...إلخ

هذا يوضح كيف يمكن للحلقات التكرارية أتمتة مهام التوليد بكفاءة عالية.