الفصل السابع: الأجسام القابلة للكسر

العب

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

الشكل 74: لوح زجاجي للاستخدام كنافذة للمبنى

الشكل 74: لوح زجاجي للاستخدام كنافذة للمبنى

ما علينا الآن هو إضافة بريمج Destructible لقالب النافذة حتى يصبح كأي وحدة بنائية أخرى في المبنى من ناحية تأثره بقوى الانفجارات. البريمج الآخر الذي نحتاجه هو البريمج Breakable والموضح في السرد 59، ومهمته هي تحويل هذه النافذة إلى جسم قابل للكسر.

1. using UnityEngine;
2. using System.Collections;
3. 
4. public class Breakable : MonoBehaviour {
5.  
6.  //الأجسام التي سيتم إنشاؤها عند الكسر (قطع الحُطام)
7.  public GameObject[] pieces;
8.  
9.  //كم من المرات سيتم تكرار كل قطعة حطام؟
10.     public int pieceCopies = 5;
11.     
12.     //كم هي القوة التي يحتاجها هذا الجسم لينكسر
13.     public float explosionPower = 10;
14.     
15.     //كم من الوقت ستبقى قطع الحطام موجودة؟
16.     public float pieceLifetime = 10;
17.     
18.     void Start () {
19.     
20.     }
21.     
22.     void Update () {
23.     
24.     }
25.     
26.     //قم بكسر الجسم
27.     public void Break(){
28.         //قم بإنشاء قطع الحطام تبعا لعددها المحدد
29.         foreach(GameObject piecePrefab in pieces){
30.             for(int i = 0; i < pieceCopies; i++){
31.                 GameObject piece = 
32.                     (GameObject)Instantiate(piecePrefab);
33.                 
34.                 //قم باختيار موقع عشوائي للإنشاء
35.                 //يجب أن يكون الموقع ضمن حدود الجسم الأصلي
36.                 Vector3 borders = transform.localScale;
37.                 Vector3 randPos;
38.                 
39.                 randPos.x = 
40.                  Random.Range(-borders.x * 0.5f, borders.x * 0.5f);
41.                 
42.                 randPos.y = 
43.                  Random.Range(-borders.y * 0.5f, borders.y * 0.5f);
44.                 
45.                 randPos.z = 
46.                  Random.Range(-borders.z * 0.5f, borders.z * 0.5f);
47.                 
48.                 //قم بوضع قطعة الحطام في الموقع العشوائي
49.                 piece.transform.position = 
50.                     transform.position + randPos;
51.                 
52.                 Vector3 explosionPos = transform.position;
53.                float explosionRad = transform.localScale.magnitude;
54.                 
55.                 piece.rigidbody.AddExplosionForce(explosionPower,
56.                                           explosionPos,
57.                                         explosionRad);
58.                 
59.                 //إن وُجد وقت محدد للإبقاء على قطع الحطام
60.                 //قم بتدمير القطع بعد هذا الوقت
61.                 if(pieceLifetime > 0){
62.                     Destroy(piece, pieceLifetime);
63.                 }
64.             }
65.         }
66.         
67.         //قم بإعلام البريمجات الأخرى بأن هذا الجسم تم كسره
68.          SendMessage("OnBreak", SendMessageOptions.DontRequireReceiver);
69.         
70.         //قم أخيرا بتدمير الجسم وحذفه من المشهد
71.         Destroy(gameObject);
72.         
73.     }
74. }

السرد 59: البريمج الخاص بالأجسام القابلة للكسر

بما أننا سنعمل على استبدال الكائن الأصلي بمجموعة من قطع الحطام عند تكسره، يلزمنا أن نقوم بتحديد هذه القطع وتزويدها عن طريق المصفوفة pieces. يمكننا كذلك عن طريق المتغير pieceCopies أن نضبط عدد النسخ التي سنقوم بإنشائها من كل قالب قطعة حطام في المصفوفة pieces. معنى ذلك أنه لو كان عندك – مثلا – قالبان لقطعتي حطام في المصفوفة pieces وقمت بضبط قيمة pieceCopies على 5، فإنك ستحصل على 10 قطع حطام عند تكسير الكائن. عند تكسير الكائن فإنه يصدر قوة انفجار يمكن تحديدها عن طريق المتغير explosionPower، مما يؤثر على قوة تنافر عدد قطع الحطام بعيدا عن الجسم. جدير بالذكر أن قوة الانفجار هذه ستطبق فقط على قطع الحطام لتنثرها بعيدا عن موقع الجسم الأصلي ولكنها لا تؤثر على أي من الكائنات الأخرى المحيطة. يمكننا أخيراً أن نقوم بتحديد الفترة الزمنية التي سنبقي فيها على قطع الحطام قبل حذفها من المشهد، وذلك عبر المتغير pieceLifeTime. بضبط قيمة هذا المتغير على صفر أو أقل يمكنك الإبقاء على قطع الحطام في المشهد بشكل دائم.

في اللحظة التي نقرر فيها أن هذا الكائن يجب أن يتكسر نقوم باستدعاء الدّالة ()Break والتي تقوم بثلاث مهام: إنشاء نسخ من قطع الحطام، وإبلاغ البريمجات الأخرى على الكائن بأنّ الكائن تم كسره وذلك عن طريق إرسال الرسالة OnBreak، ومن ثم تقوم أخيرا بحذف الكائن من المشهد. الجزء المثير للاهتمام هنا هو الحلقتان المتداخلتان foreach و for، حيث تقوم الحلقة الخارجية بالمرور على جميع القوالب الموجودة في المصفوفة pieces وتقوم بتنفيذ الداخلية والتي تتكرر بعدد يساوي pieceCopies بهدف إنشاء العدد المطلوب من قطع الحطام من كل قالب. عند إنشاء كل قطعة حطام يتم وضعها في موقع عشوائي يقع ضمن حدود الكائن الأصلي، والتي يمكننا تحديدها باستخدام القيم المحلية لقياس الكائن transform.localScale. بعد وضع قطعة الحطام في موقعها العشوائي نضيف إليها قوة الانفجار التي حددناها عبر المتغير explosionPower، آخذين في الحسبان مركز الجسم الأصلي كمركز للانفجار، مما يؤدي لتناثر كافة قطع الحطام بعيدا عن مركز الجسم. بهذا تكون قطعة الحطام جاهزة، وكل ما علينا هو استدعاء التدمير المتأخر لها في حال كانت قيمة pieceLifeTime أكبر من الصفر. بعد تجهيز كافّة قطع الحطام يتم إرسال الرسالة OnBreak ومن بعدها يتم أخيرا تدمير الكائن الأصلي.

استدعاء الدّالة ()Destroy لا يعني أن Unity سيقوم بتدمير الكائن لحظيا، إنما يقوم بتأخير تدمير هذا الكائن حتى نهاية تصيير الإطار الحالي مما يعطي الفرصة للكائنات الأخرى والبريمجات الأخرى أن تستجيب وتتعامل مع نتائج تدمير الكائن خلال الإطار الحالي

بقي علينا خطوة أخيرة حتى نجعل النوافذ التي أضفناها للمبنى الموجود في المشهد scene19 قابلة للكسر. نحتاج لبريمج يعمل على ربط البريمجين Destructible و Breakable ببعضهما. هذا البريمج سيعمل على استقبال الرسالة OnDestruction وإرسال الرسالة Break بناء على ذلك. البريمج بسيط التركيب ويسمى BreakOnDestruct وهو موضح في السرد 60. النتيجة النهائية يمكن أيضا مشاهدتها وتجربتها في المشهد scene19 في المشروع المرفق.

1. using UnityEngine;
2. using System.Collections;
3. 
4. public class BreakOnDestruct : MonoBehaviour {
5. 
6.  void Start () {
7.  
8.  }
9.  
10.     void Update () {
11.     
12.     }
13.     
14.     //OnDestruction قم باستقبال الرسالة
15.     //Breakومن ثم إرسال الرسالة 
16.     void OnDestruction(){
17.         SendMessage("Break", SendMessageOptions.DontRequireReceiver);
18.     }
19. }

السرد 60: بريمج يستقبل الرسالة OnDestruction ويقوم عندها بإرسال الرسالة Break

السابقالتالي

تعليقات واستفسارات