كيفية عمل تأثير التحطم في محرك Unity

unity

طبيعة الالعاب انها تعزلك عن العالم الواقعي وتدمجك في عالمها الخيالي، وحتى هذه الألعاب التي تتسم بأنها واقعية، في النهايه كلنا نعرف انها غير واقعية على الإطلاق. 

فليس من المنطق أن تقدر على تدمير جيوش كامله بمفردك، أو تلقي مائة طلقة ومع هذا تبقى على قيد الحياة، أو أن تتمكن من قيادة جميع أنواع المركبات المدنية والحربية من سيارات وطائرات ودبابات ورغم ذلك لا تستطيع السباحة.

بلا شك هذا ما يميز هذه الألعاب ويلجئنا إليها، لكي ندخل في عالم افتراضي بدون عواقب لأفعالنا مهما بلغت من سوء.

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

لكن اسوأ سيناريو ممكن هو ان لا تنكسر هذه الجرة بعد أن ضربتها بالميولنير، لا شك أن هذا محبط جدا، و يعني ان المطور لم يضف قابلية التدمير مما قد يقلل تقييمك لها بطريقة ما.

حسنا، لحسن الحظ لن يكون هذا الشخص انت، فبعد هذه المقالة ستتمكن من جعل كل عنصر في لعبتك قابل للتدمير والتكسير لإشباع رغبات اللاعب التخريبية.

فكرة التقنية

بالاساس تحتاج العنصر نفسه الذي تريد جعله قابلها للتحطيم او التكسير، وأعني هنا المجسم الخاص به بكل متعلقاته، ثم حدث ما ليكسره والذي يمكنك تحديده لحدث مثل السقوط من ارتفاع كبير، ضربه بواسطة مطرقة، او حتي انفجار قريب منه.

ولكن العنصر نفسه لن يتحطم بسبب هذه القوي، وانما تبديله لحظة وقوع الحدث بأخر محطم يعطي هذا الوهم، وهذا الآخر  تجهزه مسبقا واضفت اليه الخواص الفيزيائية.

تحطيم المجسم

في البداية قبل فتح محرك الالعاب تحتاج أولا أن تقسم المجسم لعدة اجزاء كأنه محطم، بالنسبة لي استخدم برنامج بلندر – Blender لهذا الغرض، ويمكنك استعمال اي برنامج اخر متاح لديك طالما يؤدي نفس الغرض.

وعملية شطره ليست يدويه، وانما بواسطة احدى الاضافات التي يوفرها بلندر، والتي تحتاج لتفعيلها اولا من خلال قائمة تفضيلات-Preferences ثم من قسم الاضافات-Add-ones، تبحث عن cell fracture ثم فعلها.

وما انوي تكسيره هو هذه الجرة الفخارية والتي يمكنك ايجادها هنا، فبعد استيرادها في بلندر، افتح نافذة الـ Cell fracture عن طريق قائمة Object >> Quick Effects >> Cell Fracture، ويمكنك الان رؤية العديد من الخيارات.

ما يهم منها الان هو الـ Source Limit، والذي يحدد عدد القطع التي تتولد للشكل المحطم، وبالنسبة لي فقد اخترت ان اجعلها 10، ويستحسن عند اختيارك للرقم الا يكون كبيرا لكي لا يتسبب بمشاكل في الاداء لاحقا بداخل المحرك.

بعد ذلك صدر الجرة المحطمة عن طريق إخفاء الجرة الأصلية اولا، ثم تحديد جميع عناصر المحطمة منها، ومن نافذة التصدير تأكد من تفعيل خيار الكائنات المُحددة – Selected Objects.

وبنفس الطريقة صدر الجرة الاصليه بعد اظهارها واخفاء الأجزاء المحطمة منها، وهكذا انتهى عمل بلندر.

التجهيز بداخل المحرك

بعد انتقالك ليونتي تحتاج أولا تجهيز كلا من الجرة ونسختها المحطمة، بالنسبة للجرة نفسها فما عليك سوى وضع الخامه – Material خاصتها، بالإضافة لمُركبتي مصادم المنمذج – Mesh Collider، والجسم الجاسئ – Rigidbody، ثم إنشاء مورد – Prefab لها.

اما بالنسبه للنسخه المحطمة منها فالطريقة نفسها تقريبا، الفرق الوحيد أن ما اضفته ليس للعنصر الأساسي نفسه، وإنما لجميع العناصر المندرجة تحته، وتأكد أن زاوية الدوران لهم مطابقة للجرة الأصليه الغير محطمه.

وبهذا يتبقى إنشاء الشيفرة – script التي تبدل الجرة الأصلية بالمحطمة، ولكن قبل هذا ينبغي معرفة ما هي الخطوات المسؤولة تحديدا عن تحطيم الجرة.

اضافة المنطق البرمجي 

في البداية ذكرت عدة أحداث لتحطم (أنفجار-تحطيم بمطرقة-الخ)، بالنسبة لي اخترت أسهلها وهو السقوط على الأرض، حيث أريد أن تتولد النسخة المحطمة اولا عندما ترتطم بسرعة معينة، ثم تدمير الاصلية.

لكن عادة عند توليدك أي كائن فلا تستطيع الرجوع اليه مجددا، بمعني انه اذا قمت بتوليد كرة على سبيل المثال تحمل مركبة المصادم، فإذا قررت بعد ذلك ان تغير اي شيء في هذه المركبة أثناء تصميم اللعبة فلن تستطيع لانك لا تستطيع الاشاره او الترميز لها.

 هذه المرة تحتاج للتحكم بالجرة المحطمة بعد توليدها، ولحل هذه المشكلة ما عليك سوى تخزين الجرة المحطمة التي تولدت في المشهد في متغير خاص بها.

using UnityEngine;
public class DestroyableObject : MonoBehaviour
{
// الجسم الجاسئ الخاص بالجرة الاصليه
    Rigidbody rb;
// المورد الخاص بالنسخه المحطمة منها والذي يتواجد في ملفات المشروع
    public GameObject brokenPotPrefab;


// المتغير الذي يرمز للنسخة المحطمة التي تولدت بالفعل في المشهد 
    GameObject brokenInstance;
   
    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }


    private void OnCollisionEnter(Collision other)
    {
// للتأكد من أنه لم تتولد اي نسخه قبل هذا
        if(brokenInstance == null)
        {
// توليد النسخة المحطمة في المشهد وتخزينها في المتغير الخاص بها
            brokenInstance = Instantiate(brokenPotPrefab،transform.position،transform.rotation);
        }
// تدمير الجرة الاصليه في النهاية
        Destroy(this.gameObject);
    }
}

ونتيجة هذا كما تري هنا، بمجرد اصطدام الجره بالارض تتحطم بالفعل، لكن توجد الآن مشكلتان، الاولى ان الجرة تتحطم دائما بمجرد ملامستها لأي سطح آخر – حتى لو ريشة – وما أريده هو تحطمها في حالة كانت سرعتها اكبر من كمية معينة كافية لتحطيمها.

الثانيه وهي ان الجرة عندما تتحطم تبدو جامدة بطريقة مزعجة، و لتحسين كيفية تحطمها تحتاج لإعطاء الأجزاء المحطمة منها متجه ومقدار السرعة الخاص بالجرة قبل تحطمها.

using UnityEngine;
public class DestroyableObject : MonoBehaviour
{
    Rigidbody rb;
    public GameObject brokenPotPrefab;
    public GameObject brokenInstance;
// قيمة السرعة الأدنى التي تحطم الجرة
    public float breakVelocity;
// مصفوفة الجسم الجاسئ التي ستحتوي على جميع مركبات الأجسام الجاسئة المحطمة
    public Rigidbody[] childsRB;


    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }
    private void OnCollisionEnter(Collision other)
    {
// طباعة سرعة الاصطدام الرأسية للمساعدة في تحديد السرعة المطلوبة للتحطيم
        Debug.Log(other.relativeVelocity);
// التحقق ان سرعة الاصطدام الرأسية كافية لتحطيم
        if(other.relativeVelocity.y > breakVelocity)
        {
            if(brokenInstance == null)
            {
                brokenInstance = Instantiate(brokenPotPrefab،transform.position،transform.rotation);
// إلحاق جميع مركبات الجسم الجاسئ داخل المصفوفة الخاصة بهم
                childsRB = brokenInstance.GetComponentsInChildren<Rigidbody>();
                foreach (Rigidbody child in childsRB)
                {
// إضافة سرعة لكل الاجزاء المحطمة مكافأة لسرعة الجرة الأصلية لحظة التحطم
                    child.velocity = rb.velocity;
                }
            }
            Destroy(this.gameObject);
        }
    }
}

ويمكنك الآن أن ترى كيف تحسنت طريقة التحطم, والتي تبدو واقعية اكثر, فالان عند ارتطام الجرة بالأرض بالسرعه الكافيه تتولد النسخة المحطمة.

ولكن المشكلة تكمن في سرعة النسخه المحطمة لحظة التولد والتي تساوي الصفر – بما انها كائن جديد لم يكتسب أي سرعة بعد – وللتغلب علي هذه المشكلة ما عليك سوى إعطاء النسخة المحطمة سرعة معينة لحظة تولدها, وهذه السرعة تساوي سرعة الجرة الاصليه قبل تحطمها تماما.

ليست مجرد زينة

وختاما فإن تحطيم العناصر ليس مجرد ميزة تجميلية في ألعاب الفيديو، بل هو أداة قوية لخلق تجارب أكثر تفاعلية ومتعة، ومع الإبداع والتفكير، يمكنك استخدام تحطيم العناصر لخلق ألعاب مُثيرة تُبهر اللاعبين وتُبقهم مُتفاعلين.

والأمر لا يتوقف عند هذا الحد، باستكشافك لإمكانيات جديدة واستخدامك للبرمجة والتصميم بطريقة مبتكرة، يمكنك جعل تحطيم الأشياء هو العنصر الأساسي في تجربة لعبتك.

0 0 votes
Article Rating
Subscribe
نبّهني عن
guest

0 تعليقات
Inline Feedbacks
View all comments