تكتسب ألعاب الدفاع عن البرج شعبية ، وهذا ليس مفاجئًا - لا يمكن مقارنة القليل بمتعة مراقبة خطوط الدفاع الخاصة بك التي تدمر الأعداء الأشرار! في هذا البرنامج التعليمي المكون من جزأين ، سنقوم بإنشاء لعبة برج الدفاع على محرك
الوحدة !
سوف تتعلم كيفية القيام بما يلي:
- خلق موجات من الأعداء
- اجعلهم يتبعون نقاط الطريق
- قم ببناء الأبراج وترقيتها ، وتعليمهم أيضًا كيفية تقسيم الأعداء إلى وحدات بكسل صغيرة
في النهاية ، نحصل على إطار اللعبة ، والذي يمكن تطويره أكثر!
ملاحظة : أنت بحاجة إلى معرفة الوحدة الأساسية (على سبيل المثال ، تحتاج إلى معرفة كيفية إضافة الأصول والمكونات ، وما هي العناصر الجاهزة) وأساسيات C # . لمعرفة كل هذا ، أوصيك بالاطلاع على البرامج التعليمية حول Unity من خلال Sean Duffy أو Beginning C # with Unity series بواسطة Brian Mockley.
سأعمل في Unity لنظام التشغيل OS X ، ولكن هذا البرنامج التعليمي مناسب أيضًا لنظام التشغيل Windows.
من خلال نوافذ برج العاج
في هذا البرنامج التعليمي ، سنقوم بإنشاء لعبة برج الدفاع حيث يزحف الأعداء (البق الصغير) إلى ملف تعريف الارتباط الخاص بك أنت وأتباعك (بالطبع ، هذه وحوش!). يمكن للاعب وضع الوحوش في نقاط استراتيجية وترقيتها للذهب.
يتعين على اللاعب قتل كل الأخطاء حتى يصل إلى ملف تعريف الارتباط. أصبحت كل موجة جديدة من الأعداء صعبة الهزيمة بشكل متزايد. تنتهي اللعبة عندما تنجو من كل الموجات (النصر!) أو عندما يزحف خمسة أعداء إلى ملفات تعريف الارتباط (الخسارة!).
فيما يلي لقطة شاشة للعبة النهائية:
وحوش ، اتحدوا! حماية ملف تعريف الارتباط!للوصول إلى العمل
قم بتنزيل هذا
المشروع فارغًا وفك ضغطه وافتح مشروع
TowerDefense-Part1-Starter في الوحدة.
يحتوي مشروع المشروع على أصول من الرسومات والأصوات والرسوم المتحركة الجاهزة والعديد من النصوص المفيدة. لا ترتبط النصوص مباشرة بألعاب الدفاع عن البرج ، لذلك لن أتحدث عنها هنا. ومع ذلك ، إذا كنت ترغب في معرفة المزيد حول إنشاء الرسوم المتحركة ثنائية الأبعاد في Unity ، فراجع
البرنامج التعليمي Unity 2D هذا.
يحتوي المشروع أيضًا على المباني الجاهزة ، والتي سنضيفها لاحقًا لإنشاء الشخصيات. أخيرًا ، هناك مشهد في المشروع بخلفية وواجهة مستخدم مخصصة.
افتح
GameScene الموجود في مجلد
Scenes واضبط وضع اللعبة على نسبة عرض إلى ارتفاع
4: 3 بحيث تتطابق جميع التسميات مع الخلفية بشكل صحيح. في وضع اللعبة ، سترى ما يلي:
التأليف:- تؤخذ رسومات المشروع من حزمة Wiki Wenderlich المجانية! يمكن العثور على أعمال الرسم الأخرى على موقع gameartguppy لها.
- موسيقى رائعة مأخوذة من BenSound ، والتي لديها موسيقى تصويرية رائعة أخرى!
- كما أشكر مايكل جيسبر على وظيفة اهتزاز الكاميرا المفيدة جدًا .
.
المكان مميز بعلامة: موقع الوحوش
يمكن وضع الوحوش فقط على النقاط المميزة بعلامة
× .
لإضافتها إلى المشهد ، اسحب
Images \ Objects \ Openspot من
Project Browser إلى نافذة
Scene . في حين أن الموقف ليس مهما بالنسبة لنا.
بمجرد تحديد
Openspot في التسلسل الهرمي ، انقر فوق
إضافة مكون في
المفتش وحدد
Box Collider 2D . في نافذة المشهد ، ستعرض الوحدة مصادم مستطيل بخط أخضر. سنستخدم هذا المصادم للتعرف على نقرات الماوس في هذا الموقع.
إضافة مكون
Audio / Audio Source إلى
Openspot بنفس الطريقة. بالنسبة لمعلمة
AudioClip لمكون مصدر الصوت ، حدد ملف
tower_place الموجود في مجلد
الصوت وقم بتعطيل
Play On Awake .
نحن بحاجة إلى إنشاء 11 نقطة أخرى. على الرغم من وجود إغراء لتكرار كل هذه الخطوات ، فإن الوحدة لديها حل أفضل:
الجاهزة !
اسحب
Openspot من
التسلسل الهرمي إلى مجلد
Prefabs داخل
Project Browser . سيتحول اسمه إلى اللون الأزرق في التسلسل الهرمي ، مما يعني أنه مرتبط بالابتكار. شيء من هذا القبيل:
الآن بعد أن أصبح لدينا فراغ فارغ ، يمكننا إنشاء العديد من النسخ كما نشاء. ما عليك
سوى سحب وإفلات
Openspot من مجلد
Prefabs داخل
Project Browser في نافذة
Scene . كرر هذا 11 مرة و 12 كائنًا مفتوحًا ستظهر في المشهد.
الآن استخدم
المفتش لتعيين هذه الكائنات الـ 12 المفتوحة مع الإحداثيات التالية:
- (X: -5.2 ، Y: 3.5 ، Z: 0)
- (X: -2.2 ، Y: 3.5 ، Z: 0)
- (X: 0.8 ، Y: 3.5 ، Z: 0)
- (X: 3.8 ، Y: 3.5 ، Z: 0)
- (X: -3.8 ، Y: 0.4 ، Z: 0)
- (X: -0.8 ، Y: 0.4 ، Z: 0)
- (X: 2.2 ، Y: 0.4 ، Z: 0)
- (X: 5.2 ، Y: 0.4 ، Z: 0)
- (X: -5.2 ، Y: -3.0 ، Z: 0)
- (X: -2.2 ، Y: -3.0 ، Z: 0)
- (X: 0.8 ، Y: -3.0 ، Z: 0)
- (X: 3.8 ، Y: -3.0 ، Z: 0)
عند القيام بذلك ، سيبدو المشهد كما يلي:
نضع الوحوش
لتبسيط الموضع ، هناك إعداد مسبق من
Monster في مجلد
Prefab للمشروع.
الوحش الجاهزة الجاهزة للاستخدامفي الوقت الحالي ، يتكون من كائن لعبة فارغ مع ثلاثة نقوش مختلفة وتصوير الرسوم المتحركة كأطفال.
كل العفريت هو وحش بمستويات مختلفة من القوة. يحتوي الإعداد المسبق أيضًا على مكون
مصدر الصوت ، والذي سيتم إطلاقه لتشغيل الصوت عندما يطلق الوحش ليزر.
الآن سنقوم بإنشاء برنامج نصي
سيستضيف Monster على
Openspot .
في
Project Browser ، حدد كائن
Openspot في مجلد
Prefabs . في
المفتش ، انقر فوق
Add Component ، ثم حدد
New Script وقم بتسمية البرنامج النصي
PlaceMonster . حدد
C Sharp كلغة وانقر على
إنشاء وإضافة . نظرًا لأننا أضفنا النص البرمجي إلى
الإعداد المسبق لـ
Openspot ، فستحتوي الآن جميع كائنات Openspot في المشهد على هذا النص البرمجي. عظيم!
انقر نقرًا مزدوجًا فوق البرنامج النصي لفتحه في IDE. ثم أضف متغيرين:
public GameObject monsterPrefab; private GameObject monster;
سنقوم بإنشاء مثيل للكائن المخزن في
monsterPrefab
لإنشاء الوحش ، وتخزينه في
monster
بحيث يمكن معالجته أثناء اللعبة.
وحش واحد لكل نقطة
بحيث يمكن وضع وحش واحد فقط على نقطة واحدة ، أضف الطريقة التالية:
private bool CanPlaceMonster() { return monster == null; }
في
CanPlaceMonster()
يمكننا التحقق مما إذا كان متغير
monster
لا يزال
null
. إذا كان الأمر كذلك ، فلا يوجد وحش في هذه النقطة ، ويمكننا وضعه.
الآن أضف الكود التالي لوضع الوحش عندما ينقر اللاعب على GameObject هذا:
يحدد هذا الرمز موقع الوحش عند النقر بالماوس أو لمس الشاشة. كيف يعمل؟
- تقوم الوحدة تلقائيًا باستدعاء
OnMouseUp
عندما يلمس اللاعب المصادم الفعلي GameObject. - عند استدعاء هذا الأسلوب يضع وحش إذا
CanPlaceMonster()
true
. - نقوم بإنشاء وحش باستخدام طريقة
Instantiate
، التي تنشئ مثيلًا من البادئة المحددة مع الموضع والدوران المحددين. في هذه الحالة ، نقوم بنسخ monsterPrefab
، ونعطيه وضع GameObject الحالي وعدم الدوران ، ونقل النتيجة إلى GameObject
وحفظها في monster
- في النهاية ، ندعو
PlayOneShot
لتشغيل المؤثر الصوتي المرتبط AudioSource
للكائن.
الآن يمكن أن يحتوي نص
PlaceMonster
على وحش جديد ، ولكن ما زلنا بحاجة إلى تحديد الإعداد المسبق.
باستخدام الجاهزة الجاهزة
احفظ الملف وارجع إلى الوحدة.
لتعيين متغير
monsterPrefab ، حدد أولاً كائن
Openspot من مجلد
Prefabs في متصفح المشروع.
في
المفتش ، انقر فوق الدائرة الموجودة على يمين حقل
Monster Prefab لمكون PlaceMonster (Script) وحدد
Monster في مربع الحوار الذي يظهر.
هذا كل شيء. قم بتشغيل المشهد وإنشاء الوحوش في أماكن مختلفة عن طريق النقر بالماوس أو لمس الشاشة.
عظيم! الآن يمكننا إنشاء وحوش. ومع ذلك ، فإنها تبدو وكأنها فوضى غريبة ، لأن كل الأطفال الوحشيين من الوحوش يتم رسمهم. الآن سنقوم بإصلاحه.
رفع مستوى الوحوش
يوضح الشكل أدناه أنه مع زيادة المستوى ، تبدو الوحوش مخيفة أكثر فأكثر.
ما هذا لطيف! ولكن إذا حاولت سرقة ملفات تعريف الارتباط الخاصة به ، فسوف يتحول هذا الوحش إلى قاتل.يتم استخدام البرنامج النصي كأساس لتنفيذ نظام مستويات الوحش. يتتبع قوة الوحش في كل مستوى ، وبالطبع المستوى الحالي للوحش.
أضف هذا البرنامج النصي.
حدد
Prefabs / Monster الجاهزة في
Project Browser . قم بإضافة برنامج نصي
C # جديد يسمى
MonsterData . افتح البرنامج النصي في IDE وأضف التعليمات البرمجية التالية
فوق فئة
MonsterData
.
[System.Serializable] public class MonsterLevel { public int cost; public GameObject visualization; }
لذا قمنا بإنشاء
MonsterLevel
. إنه يجمع السعر (بالذهب ، والذي سندعمه أدناه) وتمثيلًا مرئيًا لمستوى الوحش.
نضيف فوق
[System.Serializable]
بحيث يمكن تعديل مثيلات الفصل في المفتش. هذا يسمح لنا بتغيير جميع قيم فئة المستوى بسرعة ، حتى أثناء تشغيل اللعبة. هذا مفيد بشكل لا يصدق لموازنة اللعبة.
تحديد مستويات الوحش
في حالتنا ، سنقوم بتخزين
MonsterLevel
المحدد في
List<T>
.
لماذا لا تستخدم فقط
MonsterLevel[]
؟ سنحتاج إلى فهرس كائن
MonsterLevel
محدد عدة مرات. على الرغم من سهولة كتابة التعليمات البرمجية لهذا ، لا يزال يتعين علينا استخدام
IndexOf()
، الذي ينفذ وظيفة
Lists
. لا معنى لإعادة اختراع العجلة.
عادة ما تكون إعادة اختراع الدراجة فكرة سيئة.في الجزء العلوي من
MonsterData.cs ، أضف ما يلي
using
البناء:
using System.Collections.Generic;
يتيح لنا الوصول إلى هياكل البيانات المعممة حتى نتمكن من استخدام فئة
List<T>
في البرنامج النصي.
ملحوظة : التعميمات مفهوم قوي C #. تسمح لك بتحديد هياكل البيانات الآمنة للنوع دون الحاجة إلى الالتزام بالنوع. هذا مفيد لفئات الحاوية مثل القوائم والمجموعات. لمعرفة المزيد عن الهياكل العامة ، اقرأ مقدمة كتاب C # Generics .
الآن أضف المتغير التالي إلى
MonsterData
للاحتفاظ بقائمة
MonsterLevel
:
public List<MonsterLevel> levels;
بفضل التعميمات ، يمكننا أن نضمن أن
List
من
level
ستحتوي فقط على كائنات
MonsterLevel
.
احفظ الملف وانتقل إلى Unity لتكوين كل مستوى.
حدد
Prefabs / Monster في
Project Browser . يعرض
المفتش الآن حقل
المستويات لمكون MonsterData (البرنامج النصي) . اضبط
الحجم على
3 .
بعد ذلك ، قم بتعيين
التكلفة لكل مستوى:
- العنصر 0 : 200
- العنصر 1 : 110
- العنصر 2 : 120
الآن نقوم بتعيين قيم مجالات العرض المرئي.
قم بتوسيع
Prefabs / Monster في متصفح المشروع لرؤية أطفاله. اسحب الطفل
Monster0 إلى حقل
العنصر المرئي 0 .
بعد ذلك ، قم بتعيين
العنصر 1 على
Monster1 ،
والعنصر 2 على
Monster2 . يوضح ملف GIF هذه العملية:
عند تحديد
Prefabs / Monster ، يجب أن يبدو البادئة بالشكل التالي:
حدد المستوى الحالي
العودة إلى
MonsterData.cs في IDE وإضافة متغير آخر إلى
MonsterData
.
private MonsterLevel currentLevel;
في المستوى الحالي المتغير الخاص ، سنقوم بتخزين المستوى الحالي للوحش.
الآن قم بتعيين
currentLevel
مرئيًا للنصوص الأخرى. أضف الأسطر التالية إلى
MonsterData
مع تعريف متغيرات الحالة:
قطعة كبيرة من كود C # ، أليس كذلك؟ لنأخذ الأمر بالترتيب:
- قم بتعيين خاصية المستوى الحالي المتغير الخاص. من خلال تعيين الخاصية ، يمكننا
monster.CurrentLevel
مثل أي متغير آخر: إما كـ CurrentLevel
(داخل الفصل) أو monster.CurrentLevel
. يمكننا تحديد أي سلوك في طريقة getter أو setter لخاصية ، ومن خلال إنشاء getter أو setter أو كليهما فقط ، يمكننا التحكم في خصائص الخاصية: للقراءة فقط والكتابة فقط والكتابة / القراءة. - في المُدَرِّس ، نعيد قيمة
currentLevel
. - في أداة
currentLevel
، نقوم بتعيين قيمة جديدة في المستوى الحالي. ثم نحصل على مؤشر المستوى الحالي. أخيرًا ، currentLevelIndex
جميع المستويات ونمكّن / currentLevelIndex
العرض المرئي اعتمادًا على currentLevelIndex
. هذا أمر رائع لأنه عندما يتغير currentLevel
، يتم تحديث currentLevel
تلقائيًا. خصائص شيء مريح للغاية!
قم بإضافة تطبيق
OnEnable
التالي:
void OnEnable() { CurrentLevel = levels[0]; }
هنا نضع
CurrentLevel
عند وضع. هذا يضمن عرض العفريت المطلوب فقط.
ملاحظة : من المهم تهيئة الخاصية في OnEnable
، وليس في OnStart
، لأننا OnStart
الأساليب الترتيبية عند إنشاء مثيلات OnStart
.
سيتم استدعاء OnEnable
فورًا عند إنشاء OnEnable
المسبق (إذا تم حفظه في الحالة التي تم تمكينها) ، ولكن لا OnStart
استدعاء OnStart
حتى يبدأ تشغيل الكائن كجزء من المشهد.
نحتاج إلى التحقق من هذه البيانات قبل وضع الوحش ، لذلك نقوم OnEnable
إلى OnEnable
.
احفظ الملف وارجع إلى الوحدة. تشغيل المشروع ووضع الوحوش ؛ يعرضون الآن العفاريت الصحيحة من أدنى مستوى.
ترقية الوحش
العودة إلى IDE وإضافة الطريقة التالية إلى
MonsterData
:
public MonsterLevel GetNextLevel() { int currentLevelIndex = levels.IndexOf (currentLevel); int maxLevelIndex = levels.Count - 1; if (currentLevelIndex < maxLevelIndex) { return levels[currentLevelIndex+1]; } else { return null; } }
في
currentLevel
نحصل على فهرس الحالي ومستوى أعلى مستوى ؛ إذا لم يصل الوحش إلى المستوى الأقصى ، فسيعود المستوى التالي. خلاف ذلك ،
null
إرجاع قيمة
null
.
يمكنك استخدام هذه الطريقة لمعرفة ما إذا كانت ترقية الوحش ممكنة.
لرفع مستوى الوحش ، أضف الطريقة التالية:
public void IncreaseLevel() { int currentLevelIndex = levels.IndexOf(currentLevel); if (currentLevelIndex < levels.Count - 1) { CurrentLevel = levels[currentLevelIndex + 1]; } }
هنا نحصل على فهرس المستوى الحالي ، ثم نتأكد من أن هذا ليس الحد الأقصى للمستوى ، مع التأكد من أنه أقل من
levels.Count - 1
. إذا كان الأمر كذلك ،
CurrentLevel
إلى المستوى التالي.
التحقق من وظيفة الترقية
احفظ الملف
وارجع إلى
PlaceMonster.cs في IDE. أضف طريقة جديدة:
private bool CanUpgradeMonster() { if (monster != null) { MonsterData monsterData = monster.GetComponent<MonsterData>(); MonsterLevel nextLevel = monsterData.GetNextLevel(); if (nextLevel != null) { return true; } } return false; }
أولاً ، نتحقق مما إذا كان هناك وحش يمكن تحسينه بمقارنة متغير
monster
null
. إذا كان هذا صحيحًا ، فإننا نحصل على مستوى الوحش الحالي من
MonsterData
.
ثم نتحقق مما إذا كان المستوى التالي متاحًا ، أي ما إذا كان
GetNextLevel()
لا يرجع
null
. إذا كان من الممكن زيادة المستوى ، فإننا نعود
true
؛ خلاف ذلك إرجاع
false
.
نطبق تحسينات للذهب
لتمكين خيار الترقية ، أضف الفرع
else if
الفرع إلى
OnMouseUp
:
if (CanPlaceMonster()) {
نتحقق من إمكانية الترقية باستخدام
CanUpgradeMonster()
. إذا أمكن ، نصل إلى مكون
MonsterData
باستخدام
GetComponent()
IncreaseLevel()
، مما يزيد من مستوى الوحش. أخيرًا ، أطلقنا Monster
AudioSource .
احفظ الملف وارجع إلى الوحدة. قم بتشغيل اللعبة ووضع وترقية
أي عدد من الوحوش (ولكن في الوقت الحالي).
دفع الذهب - مدير اللعبة
بينما يمكننا بناء وتحسين أي وحوش على الفور ، ولكن هل سيكون الأمر مثيرًا للاهتمام في اللعبة؟
دعونا نلقي نظرة على قضية الذهب. مشكلة التتبع هي أنه يتعين علينا نقل المعلومات بين كائنات اللعبة المختلفة.
يوضح الشكل أدناه جميع الأشياء التي يجب أن تشارك في هذا.
يجب أن تعرف جميع كائنات اللعبة المختارة مقدار الذهب الذي يمتلكه اللاعب.لتخزين هذه البيانات ، سنستخدم كائنًا مشتركًا يمكن للكائنات الأخرى الوصول إليه.
انقر بزر الماوس الأيمن على
التسلسل الهرمي وحدد
إنشاء فارغ . اسم كائن
GameManager الجديد.
قم بإضافة برنامج نصي جديد لـ
C # يسمى
GameManagerBehavior إلى GameManager ، ثم قم بفتحه في IDE. سنعرض المبلغ الإجمالي للاعب الذهب في الملصق ، لذا في الجزء العلوي من الملف ، أضف السطر التالي:
using UnityEngine.UI;
سيسمح لنا هذا بالوصول إلى فئات واجهة المستخدم مثل
Text
، والتي يتم استخدامها للتسميات. الآن أضف المتغير التالي إلى الفصل:
public Text goldLabel;
سيقوم بتخزين رابط لمكون
Text
المستخدم لعرض كمية الذهب التي يمتلكها اللاعب.
الآن بعد أن عرف
GameManager
عن الملصق ، كيف يمكننا مزامنة كمية الذهب المخزنة في المتغير والقيمة المعروضة في الملصق؟ سننشئ خاصية.
أضف التعليمات البرمجية التالية إلى
GameManagerBehavior
:
private int gold; public int Gold { get { return gold; } set { gold = value; goldLabel.GetComponent<Text>().text = "GOLD: " + gold; } }
هل يبدو مألوفا؟ الرمز مشابه لـ
CurrentLevel
، الذي وضعناه في
Monster
. أولاً ، نقوم بإنشاء
gold
المتغير الخاص ليحتفظ بكمية الذهب الحالية. ثم نقوم بتعيين خاصية
Gold
(بشكل غير متوقع ، أليس كذلك؟) ونطبق أداة getter و setter.
يعيد القائم بالتعليم ببساطة قيمة
gold
. أداة الإعداد أكثر إثارة للاهتمام. بالإضافة إلى تعيين قيمة المتغير ، فإنه يقوم أيضًا بتعيين حقل
text
لـ
goldLabel
لعرض القيمة الذهبية الجديدة.
كيف سنكون كرماء؟ أضف السطر التالي إلى
Start()
لمنح اللاعب
1000 ذهبية أو أقل إذا شعرت بالأسف على المال:
Gold = 1000;
تعيين كائن تسمية لبرنامج نصي
احفظ الملف وارجع إلى الوحدة. في
التسلسل الهرمي ، حدد
GameManager . في
المفتش ، انقر على الدائرة على يمين
الملصق الذهبي . في مربع الحوار
Select Text ، حدد علامة التبويب
Scene وحدد
GoldLabel .
شغّل المشهد وستعرض الملصق
Gold: 1000 .
التحقق من "محفظة" اللاعب
افتح البرنامج النصي
PlaceMonster.cs في IDE وأضف متغير المثيل التالي:
private GameManagerBehavior gameManager;
سنستخدم
gameManager
للوصول إلى مكون
GameManagerBehavior
لكائن
GameManagerBehavior
في المشهد. لتحديد ذلك ، أضف ما يلي إلى
Start()
:
gameManager = GameObject.Find("GameManager").GetComponent<GameManagerBehavior>();
نحصل على GameObject تسمى GameManager باستخدام وظيفة
GameObject.Find()
، والتي تُرجع أول كائن لعبة موجود بهذا الاسم. ثم نحصل على المكون
GameManagerBehavior
للمستقبل.
ملاحظة : يمكنك القيام بذلك عن طريق تعيين حقل في محرر الوحدة أو عن طريق إضافة طريقة ثابتة إلى GameManager
تقوم بإرجاع مثيل من المفرد الذي يمكننا من خلاله الحصول على GameManagerBehavior
.
ومع ذلك ، في كتلة التعليمات البرمجية الموضحة أعلاه ، يوجد حصان مظلم: طريقة Find
، والتي تعمل بشكل أبطأ أثناء تنفيذ التطبيق ؛ لكنها مريحة ويمكن استخدامها باعتدال.
خذ أموالي!
لم نطرح الذهب بعد ، لذلك سنضيف هذا السطر
مرتين إلى
OnMouseUp()
،
OnMouseUp()
كل التعليقات
// TODO:
:
gameManager.Gold -= monster.GetComponent<MonsterData>().CurrentLevel.cost;
احفظ الملف وارجع إلى Unity ، وقم بترقية بعض الوحوش وانظر إلى تحديث القيمة الذهبية. الآن نخصم الذهب ، ولكن يمكن للاعبين بناء وحوش طالما لديهم مساحة كافية ؛ يقترضون المال فقط.
الائتمان اللامتناهي؟ عظيم! لكن لا يمكننا السماح بذلك. يتعين على اللاعب أن يراهن على الوحوش بينما يمتلك ما يكفي من الذهب.الشيك الذهبي للوحوش
قم بالتبديل في IDE إلى
PlaceMonster.cs واستبدل محتويات
CanPlaceMonster()
يلي:
int cost = monsterPrefab.GetComponent<MonsterData>().levels[0].cost; return monster == null && gameManager.Gold >= cost;
MonsterData
سعر وضع الوحش من
levels
في
MonsterData
. ثم نتحقق من أن
monster
ليس
null
، وأن
gameManager.Gold
أكثر من هذا السعر.
المهمة بالنسبة لك: أضف بشكل مستقل إلى
CanUpgradeMonster()
تحقق مما إذا كان اللاعب لديه ما يكفي من الذهب.
الحل في الداخلاستبدل الخط:
return true;
على هذا:
return gameManager.Gold >= nextLevel.cost;
سوف يتحقق ما إذا كان اللاعب لديه
ذهب أكثر من سعر الترقية.
حفظ وتشغيل المشهد في الوحدة. جرب الآن كيفية إضافة الوحوش بشكل غير محدود!
الآن يمكننا فقط بناء عدد محدود من الوحوش.سياسة الأبراج: الأعداء والأمواج ونقاط الطريق
حان الوقت "لتمهيد الطريق" لأعدائنا. يظهر الأعداء في النقطة الأولى من المسار ، وينتقلون إلى التالي ويكرروا العملية حتى يصلوا إلى ملف تعريف الارتباط.
يمكنك جعل الأعداء يتحركون هكذا:
- ضع الطريق الذي سيتبعه الأعداء
- حرك العدو على طول الطريق
- اقلب العدو حتى يتطلع
إنشاء طريق من نقاط الطريق
انقر بزر الماوس الأيمن على
التسلسل الهرمي وحدد
إنشاء فارغ لإنشاء كائن لعبة فارغ جديد. قم بتسمية
الطريق ثم ضعه على
(0 ، 0 ، 0) .
الآن انقر بزر الماوس الأيمن على
Road في
التسلسل الهرمي وقم بإنشاء كائن لعبة فارغ آخر كطفل من Road.
اسمها Waypoint0 ووضعها عند النقطة
(-12 ، 2 ، 0) - من هنا سيبدأ الأعداء حركتهم.
وبالمثل ، قم بإنشاء خمس نقاط مسار أخرى بالأسماء والمواضع التالية:
- نقطة الطريق 1: (X: 7، Y: 2، Z: 0)
- نقطة الطريق 2: (X: 7، Y: -1، Z: 0)
- نقطة الطريق 3: (X: -7.3، Y: -1، Z: 0)
- نقطة الطريق 4: (X: -7.3، Y: -4.5، Z: 0)
- نقطة الطريق 5: (X: 7، Y: -4.5، Z: 0)
توضح لقطة الشاشة أدناه نقاط المسار والمسار الناتج.
صنع الأعداء
الآن خلق بعض الأعداء حتى يتمكنوا من التحرك على طول الطريق. يوجد إعداد سابق
للعدو في مجلد
Prefabs . موقعها هو
(-20 ، 0 ، 0) ، لذلك سيتم إنشاء مثيلات جديدة خارج الشاشة.
في جميع النواحي الأخرى ، تم تكوينه بنفس الطريقة تقريبًا مثل Monster الجاهزة ، ولديه
AudioSource
صوت وطفل
Sprite
، ويمكننا تدوير هذا العفريت في المستقبل دون تحويل شريط الصحة.
ننتقل الأعداء على طول الطريق
قم بإضافة برنامج نصي
C # جديد يسمى
MoveEnemy إلى
الإعداد المسبق Prefabs \ Enemy . افتح البرنامج النصي في IDE وأضف المتغيرات التالية:
[HideInInspector] public GameObject[] waypoints; private int currentWaypoint = 0; private float lastWaypointSwitchTime; public float speed = 1.0f;
في
waypoints
، يتم تخزين نسخة من نقاط المسار في المصفوفة ،
[HideIn inspector ]
أعلى
waypoints
أنه لا يمكننا تغيير هذا المجال عن طريق الخطأ في
المفتش ، ولكن سيظل بإمكاننا الوصول إليه من النصوص البرمجية الأخرى.
currentWaypoint
مسار العدو في الوقت الحالي ، ويخزن
lastWaypointSwitchTime
الوقت الذي يمر فيه العدو. بالإضافة إلى ذلك ، نقوم بتخزين
speed
العدو.
أضف هذا السطر إلى
Start()
:
lastWaypointSwitchTime = Time.time;
لذلك نقوم بتهيئة
lastWaypointSwitchTime
بقيمة الوقت الحالي.
لكي يتحرك العدو على طول المسار ، أضف الرمز التالي إلى
Update()
:
دعنا نحلل الشفرة خطوة بخطوة:
- من مصفوفة نقاط المسار ، نحصل على مواضع البداية والنهاية لجزء المسار الحالي.
- نحسب الوقت المطلوب لتغطية المسافة الكاملة باستخدام الصيغة الصيغة = المسافة / السرعة ، ثم نحدد الوقت الحالي على الطريق. باستخدام
Vector2.Lerp
، نقوم باستيفاء الموقع الحالي للعدو بين بداية ونهاية الجزء المحدد. - تحقق مما إذا كان العدو قد وصل إلى
endPosition
. إذا كانت الإجابة بنعم ، فإننا نعالج سيناريوهين محتملين:
- لم يصل العدو بعد إلى النقطة الأخيرة من المسار ، لذا قم بزيادة قيمة
currentWaypoint
وتحديث lastWaypointSwitchTime
. في وقت لاحق سنضيف رمزًا لتحويل العدو حتى ينظر في اتجاه حركته. - وصل العدو إلى النقطة الأخيرة من الطريق ، ثم ندمره ونبدأ التأثير الصوتي. سنضيف لاحقًا رمزًا يقلل من
health
اللاعب.
احفظ الملف وارجع إلى الوحدة.
نبلغ الأعداء باتجاه الحركة
في وضعهم الحالي ، لا يعرف الأعداء ترتيب نقاط الطريق.
حدد
طريق في
التسلسل الهرمي وأضف سكريبت
C # جديد يسمى
SpawnEnemy . افتحها في IDE وأضف المتغير التالي:
public GameObject[] waypoints;
سوف نستخدم
waypoints
لتخزين المراجع لنقطة الطريق في المشهد بالترتيب المطلوب.
احفظ الملف وارجع إلى الوحدة. حدد
طريقًا في
التسلسل الهرمي واضبط
حجم نقاط نقاط الطريق على
6 .
اسحب كل من أطفال الطريق إلى الحقول عن طريق لصق
Waypoint0 في
Element 0 و
Waypoint1 في
Element 1 وهكذا.
الآن لدينا مصفوفة تحتوي على نقاط الطريق بالترتيب الصحيح - ضع في اعتبارك أن الأعداء لا يتراجعون أبدًا ، فهم يسعون باستمرار للحصول على مكافأة رائعة.
تحقق من كيفية عمل كل شيء
افتح
SpawnEnemy في IDE وأضف المتغير التالي:
public GameObject testEnemyPrefab;
ستقوم بتخزين مرجع إلى
testEnemyPrefab
للعدو في
testEnemyPrefab
.
لإنشاء عدو عند تشغيل البرنامج النصي ، أضف التعليمات البرمجية التالية إلى
Start()
:
Instantiate(testEnemyPrefab).GetComponent<MoveEnemy>().waypoints = waypoints;
لذلك سنقوم بإنشاء نسخة جديدة من الجاهزة المخزنة في
testEnemy
وتعيين طريق لها.
احفظ الملف وارجع إلى الوحدة. حدد كائن
الطريق في
التسلسل الهرمي وحدد
الإعداد المسبق
للعدو لمعلمة
اختبار العدو .
قم بتشغيل المشروع وانظر كيف يتحرك العدو على طول الطريق (في GIF ، لزيادة الوضوح ، تزداد السرعة بمقدار 20 مرة).هل لاحظ أنه لا ينظر دائمًا إلى أين يذهب؟ هذا مضحك ، لكننا نحاول صنع لعبة احترافية. لذلك ، في الجزء الثاني من البرنامج التعليمي ، سنعلم الأعداء التطلع إلى المستقبل.إلى أين أذهب بعد ذلك؟
لقد فعلنا الكثير بالفعل ونتحرك بسرعة نحو إنشاء لعبة الدفاع عن البرج الخاصة بنا.يمكن للاعبين إنشاء عدد محدود من الوحوش ، والعدو يمتد على طول الطريق ، متجهًا نحو ملف تعريف الارتباط الخاص بنا. يمتلك اللاعبون الذهب ويمكنهم ترقية الوحوش.قم بتنزيل النتيجة النهائية من هنا .في الجزء الثاني ، سننظر في إنشاء موجات ضخمة من الأعداء وتدميرها. اراك قريبا!