تمت كتابة الأداة في الأصل لمساعدتك على تطوير ألعاب عرضية بسيطة في Unity ، على الأقل كانت مفيدة للغاية.
لكنني أعتقد أنني سأستخدمه في مشاريع أخرى ، وليس فقط في الوحدة.
وربما يكون مفيدًا لك أيضًا!
رابط المصدر
إذن ، ما هو الغرض منه؟
تخيل موقفًا: لقد كتبت لعبة عادية بسيطة تحتاج فيها إلى النقر على الشاشة عشر مرات لإكمال مستوى واحد ، وإرسالها إلى رئيسك (أو عميل مدلل) للمعاينة.
تليها المهام واحدة تلو الأخرى:
- دعنا نضيف إعلانات في النهاية كل 1.5 دقيقة؟
- ودعنا بعد ذلك في مكان ما في البداية ، ستكون هناك نافذة: "اشترِ علاوة حتى لا يكون هناك إعلان"؟
- شيء ما تضغط عليه هذه النافذة بشكل حاد ، ولكن دعه يكون بعد الإعلان ، ولكن فقط عندما يضغط اللاعب على زر البداية ويتخطى مستويين؟
- وتعال في المستويات 10 ، 20 ، 30 ، هل ستكون هناك نافذة "مشاركة مع الأصدقاء"؟
- وتعال من المستوى 10 كل 2 مستويات هل هناك نافذة "قيمنا!"؟
- وحفنة أكثر!
حتى بعد إجراء عملية إعدام قاسية وحظر لا نهاية له لطفلك ، بعد إجراء الفحص المائة لموقع النوافذ ، ستواجه عاجلاً أم آجلاً مثل هذه المشكلة: يمكن للنوافذ المقيدة بالمؤقت أن تتداخل مع النوافذ المرتبطة بالمستويات نفسها!
تزداد صعوبة إعادة هذا الأمر أكثر فأكثر - فبعد كل شيء ، فإن الفحوصات المشروطة تصل إلى الرقبة بالفعل ، بالإضافة إلى أن زميلك كان بإمكانه إضافة نوافذ خاصة به برمز غير قابل للقراءة تمامًا! ماذا أفعل؟
مهمة
اتصل بالنافذة في لحظة معينة (على سبيل المثال ، الضغط على زر) ، وفقط إذا تم استيفاء جميع الشروط المحددة (مر الوقت ، تم الوصول إلى النقطة المطلوبة ، وما إلى ذلك)
القرار
لهذا ، قمت بعمل فئة شرطية ، وهنا مجالاتها الرئيسية:
- تم ضبط المؤقت للثواني
- التخطي تعيين int
- List <int> checkPoints
, , . .
, , . , , , NextSkip(). = 0, ,
. - , START() — .
, StartTimer() ResetSkips(). , IsReady()
true , (value > 0), START() .
: — ( ) setedSeconds, , , !
IsReady() , START() , , .
public Condition myCondition;
void Start(){
myCondition = new Condition("");
myCondition.setedSeconds = 120; // 2
myCondition.setedSkips = 5;
myCondition.START(); //
}
//
public void FinishRound(){
myCondition.NextSkip(); // ,
if (myCondition.IsReady())
{
// , ...
myCondition.START(); // START() . , IsReady == true
}
}
, , — List <int> checkPoints. - , , , ., , - . , : , ( , ). , Sheduler , , — .
public Condition myCondition;
void Start(){
myCondition = new Condition("",new List<int> { 1, 2, 5 }); // ,
myCondition.setedSeconds = 120;
myCondition.setedSkips = 5;
myCondition.START();
}
public void FinishRound(){
myCondition.NextSkip();
if (myCondition.IsReady() || myCondition.HasCheckPoint(currentLevel)) //
{
// , ...
myCondition.START();
}
}
, , =) AutoInvoke(Action CallBack, int checkPoint = 0) , NextSkip() START() , START() .
public Condition myCondition;
void Start(){
myCondition = new Condition("",new List<int> { 1, 2, 5 });
myCondition.setedSeconds = 120;
myCondition.setedSkips = 5;
myCondition.START();
}
public void FinishRound(){
myCondition.AutoInvoke(() => Debug.Log("hello World"), currentLevel);
// currentLevel,
}
سيساعدك كائن الشرط الواحد على توفير مجموعة من الشروط الضرورية بسرعة لتشغيل أي وظيفة واحدة !!!
إذا كانت مهمتك في المهمة الفنية أصعب قليلاً من مكالمة بسيطة ، على سبيل المثال ، مكالمة كل مرة أخرى أو بعد فترة من الوقت ، فسيكون من المفيد بالفعل اللجوء إلى الشرط ، لأن هذا تجريد وإمكانية القراءة - عليك فقط أن تبدأها وتتحقق من جاهزيتها.
لقد أضفت سمات وحدة مفيدة إلى حقول الشرط لتسهيل التهيئة من خلال المفتش!
الشيء الرئيسي هو المرونة ، وإذا جاء شخص ما فجأة بوظائفه الخاصة التي لا ينبغي أن تتعارض مع حالتك ، فأنت تحتاج فقط إلى إنشاء مخطط عام ...
المهمة التالية
أضف نوافذ مختلفة (استدعاء الوظيفة) بمرونة من أماكن مختلفة في البرنامج ، حافظ على المزامنة وتجنب تعارضات التراكب!
الحل:
والآن وصلنا إلى فئة Sheduler الرئيسية ، مخطط الحالة لدينا!
من الأفضل تهيئة كائن من هذه الفئة في أقرب وقت ممكن. على وجه التحديد في الوحدة ، من الأفضل أن يكون الكائن هو DontDestroyOnLoad .
إذا نظرت داخل Sheduler ، يمكنك رؤية الحقول التالية:
- نقطة التفتيش الحالية في نقطة الفحص الحالية
- مجموعة من جميع الشروط المضافة وسلوكها القاموس ومعاملو الحالة والإجراء والظروف - بحيث
يعرف المخطط الدور الذي يجب أن يلعبه الشرط النهائي - Dictionary <int,Condition> CheckPoints — Sheduler, Dictionary, , . .
- Queue <Condition> WaitingConditions ,
يخزن Sheduler سلوك كل شرط ويتم تشغيله وفقًا لهذه الفئة ، ويتم تعيينه في وقت إضافة الشرط إضافة الفراغ العام (Condition newCondition ، Action CallBack) ، حيث يوجد مفوض مطلوب في الوسيطات. تقرأ الطريقة نفسها اسم الشرط وتلقي استثناءً إذا كان فارغًا أو تمت إضافته بالفعل - وهذا ضروري في حالة احتياجك لسبب ما إلى أخذ شرط من الجدول المسمى List & ltCondition & gt GetConditions (params string [] conditionName) . أيضًا ، تعمل طريقة الإضافة Add () فورًا على تشغيل Start () للشرط المُضاف. هذا مفيد إذا قمت بتشغيل Start ()سيتم نسيان الشرط الإضافي من خلال أي من المطورين ، وأيضًا لتجنب التخلص المستمر من هذه الوظيفة من Sheduler. إذا كنت بحاجة إلى مكان مختلف لبدء الشرط ، فأنت تعمل فقط مع الشرط كما كان من قبل ، ويمكنك دائمًا تغيير عداداته. هذا هو جمال Sheduler - فهو يتعامل مع المكان الذي يكون فيه الشرط جاهزًا ، وحيث يتم تغيير جاهزيته ، ويقوم بإجراء هذا الحساب في وقت استدعاء طريقته الرئيسية Condition Invoke (params Condition [] شارات) . في الحجج ، يمكنك تحديد بعض الشارات ، أي تلك الشروط التي يجب أن تعمل حصريًا ، وتلك التي جاء دورها ، ومع ذلك ، لم تظهر في قائمة الشارات ، فلن تعمل. ولكن ، إذا لم تحدد أي شيء ، فعندئذٍ ، كما ينبغي ، يحق لكل شخص الاتصال في ذروة قائمة الانتظار!
تأكد من التفكير في المكان الذي سيتم فيه حساب نقاط التفتيش لـ Sheduler NextCheckPoint () ، على سبيل المثال ، في الطريقة ، في النهاية أو في بداية الجولة ،
مثال كامل لما هو مطلوب للعمل مع Sheduler:
public Condition OfferBuyVip;
public Condition OfferToShareWithFriends;
public Condition OfferToVisitSite;
public Sheduler OfferSheduler;
public void Start(){
OfferSheduler = new Sheduler(currentLevel); //
/*
*
*/
OfferSheduler.Add(OfferBuyVip, () => Debug.Log(" VIP"));
OfferSheduler.Add(OfferToShareWithFriends, () => Debug.Log(" "));
OfferSheduler.Add(OfferToVisitSite, () => Debug.Log(" , "));
}
public void FinishRound(){
OfferSheduler.NextCheckPoint(currentLevel); // ,
OfferSheduler.Invoke(OfferBuyVip, OfferToShareWithFriends) // ,
}
public void StartRound(){
OfferSheduler.Invoke(OfferToVisitSite); //
// , , Sheduler
}
هذه هي الطريقة التي حققنا بها أن الوظائف الثلاث لشروطنا يتم استدعاؤها في أماكن مختلفة ، بينما يحترمون بعضهم البعض ولا يزحفون إلى كل شيء ، لكن يلاحظون قائمة الانتظار (مثل قائمة انتظار رقمية حديثة للقسائم) ، ويقفز المستخدم بسرعة من خط النهاية إلى بداية اللعبة ، لن ترهق من عدد من المقترحات. مع Sheduler ، يحافظ على انسجام واضح من البساطة والمرونة ، لأنه مع Sheduler والمفوض الذي تم تمريره إليه عبر طريقة Add (Condition newCondition ، Action CallBack) ، من الممكن تنفيذ أي اتصال بين النوافذ.
على سبيل المثال ، عند استدعاء لافتة إعلانية ، يظهر عرض شراء Premium بدون إعلان بعد مستويين:
void Start(){
OfferSheduler = new Sheduler(currentLevel);
callAddBanner = new Condition(" ");
callAddBanner.setedSeconds = 80; // 80
OfferBuyVip = new Condition(" VIP ");
OfferSheduler.Add(callAddBanner,
delegate()
{
Debug.Log(" ");
OfferBuyVip.setedSkips = 2; //
OfferBuyVip.START(); //
}
);
OfferSheduler.Add(OfferBuyVip,
delegate ()
{
Debug.Log(" VIP");
OfferBuyVip.setedSkips = 0; // !
//,
}
);
}
void Finish(){
OfferSheduler.NextCheckPoint(currentLevel); //
//
OfferSheduler.Invoke(); //
//
}
تمامًا مثل هذا ، سيتم الآن إطلاق إعلان غير مشتت للانتباه كل 80 ثانية (بعد كل شيء ، لا يتم استدعاؤه خلال جولة مهمة ، ولكن عند خط النهاية) وأيضًا يطلق عرضًا لشراء إعلان عندما يكون ذلك مناسبًا لك! وأفضل شيء هو أن أي مطور في الفريق يمكنه الآن إضافة مقترحاته إلى Sheduler ، وسيقوم Sheduler بتوزيع كل شيء.