أحد مزايا Unity كمنصة لتطوير الألعاب هو محركها القوي ثلاثي الأبعاد. في هذا البرنامج التعليمي ، ستتعرف على عالم الكائنات ثلاثية الأبعاد ومعالجة الشبكة.
نظرًا لنمو تقنيات الواقع الافتراضي والمعزز (VR / AR) ، يواجه معظم المطورين مفاهيم رسومات ثلاثية الأبعاد معقدة. دع هذا البرنامج التعليمي يكون نقطة البداية بالنسبة لهم. لا تقلق ، لن تكون هناك رياضيات ثلاثية الأبعاد معقدة - فقط القلوب والرسومات والسهام والكثير من الأشياء المثيرة للاهتمام!
ملاحظة: هذا البرنامج التعليمي مخصص للمستخدمين المطلعين على Unity IDE ولديهم بعض الخبرة في البرمجة في C #. إذا لم يكن لديك هذه المعرفة ، فقم أولاً بدراسة البرامج التعليمية مقدمة إلى Unity UI ومقدمة إلى Unity Scripting .
ستحتاج إلى إصدار Unity لا يقل عن 2017.3.1. يمكن تنزيل أحدث إصدار من Unity من هنا . يستخدم هذا البرنامج التعليمي محررًا مخصصًا ، ويمكنك معرفة المزيد عنها من البرنامج التعليمي Extended the Unity Editor .
للوصول إلى العمل
للبدء ، تعرف على الشروط الأساسية للرسومات ثلاثية الأبعاد ، والتي ستسمح لك بفهم البرنامج التعليمي بشكل أفضل.
المصطلحات التقنية الأساسية للرسومات ثلاثية الأبعاد:
- القمم : كل قمة هي نقطة في الفضاء ثلاثي الأبعاد.
- شبكة : تحتوي على جميع القمم والحواف والمثلثات والمعايير وبيانات الأشعة فوق البنفسجية للنموذج.
- تصفية شبكة : يخزن بيانات شبكة النموذج.
- Mesh Renderer : لعرض بيانات الشبكة في المشهد.
- المعايير : ناقل الرأس أو السطح. يتم توجيهها إلى الخارج ، متعامدة على سطح الشبكة.
- خطوط / حواف : خطوط غير مرئية تربط القمم ببعضها البعض.
- المثلثات : تتكون من ربط ثلاث قمم.
- خريطة الأشعة فوق البنفسجية : تعلق المواد على كائن ، مما يخلق نسيجًا ولونًا له.
يبدأ تشريح كائن ثلاثي الأبعاد بشبكته. يبدأ إنشاء هذه الشبكة في قمتها. تشكل الخطوط غير المرئية التي تربط هذه القمم مثلثات تحدد الشكل الأساسي للكائن.
ثم تقوم البيانات العادية وبيانات الأشعة فوق البنفسجية بتعيين التظليل واللون والملمس. يتم تخزين بيانات الشبكة في مرشح شبكة ، ويستخدم عارض الشبكة هذه البيانات لرسم كائن في المشهد.
أي أن الرمز الزائف لإنشاء نموذج ثلاثي الأبعاد يبدو كما يلي:
- إنشاء شبكة جديدة تسمى "myMesh".
- إضافة بيانات إلى خصائص القمم والمثلثات myMesh.
- قم بإنشاء مرشح شبكة جديد يسمى "myMeshFilter".
- قم بتعيين خاصية شبكة myMeshFilter إلى myMesh.
بمجرد أن تتقن الأساسيات ، قم بتنزيل
المشروع وفك ضغط الملفات وتشغيل قطعة عمل المشروع في Unity. انظر إلى بنية المجلد في نافذة
المشروع :
وصف المجلدات:
- Prefabs : يحتوي على Sphere الجاهزة التي سيتم استخدامها لحفظ الشبكة ثلاثية الأبعاد أثناء تنفيذ التطبيق.
- المشاهد : تحتوي على المشاهد الثلاثة التي نستخدمها في هذا البرنامج التعليمي.
- المحرر : تمنحنا النصوص البرمجية الموجودة داخل هذا المجلد الميزات الفائقة في المحرر الذي نستخدمه في التطوير.
- البرامج النصية : إليك البرامج النصية لوقت التشغيل التي ترتبط بـ GameObject ويتم تنفيذها عند النقر فوق تشغيل .
- المواد : يحتوي هذا المجلد على مادة الشبكة.
في القسم التالي ، سننشئ محررًا مخصصًا لتصور إنشاء شبكة ثلاثية الأبعاد.
تغيير الشبكات باستخدام محرر مخصص
افتح
العرض التوضيحي 01 Mesh Study الموجود في مجلد
Scenes . في نافذة
المشهد ، سترى مكعبًا ثلاثي الأبعاد:
قبل الدخول في الشبكة ، دعنا نلقي نظرة على البرنامج النصي المحرر المخصص.
تحرير برنامج نصي محرر
حدد مجلد
Editor في نافذة
Project . تضيف البرامج النصية في هذا المجلد وظائف إلى المحرر (المحرر) أثناء التطوير ولا تتوفر في وضع البناء.
افتح
MeshInspector.cs وعرض التعليمات البرمجية المصدر. يجب أن تنفذ جميع البرامج النصية الخاصة
Editor
فئة
Editor
، حيث
CustomEditor
سمة
CustomEditor
فئة
Editor
بنوع الكائن المخصص لها.
OnSceneGUI()
هي طريقة حدث تسمح
OnSceneGUI()
في نافذة المشهد ؛ يسمح لك
OnInspectorGUI()
بإضافة عناصر GUI إضافية إلى المفتش.
في
MeshInspector.cs ، قبل بدء فئة
MeshInspector
أضف ما يلي:
[CustomEditor(typeof(MeshStudy))]
شرح الكود:
CustomEditor
السمة
CustomEditor
الوحدة بنوع الكائن الذي يمكن لفئة المحرر المخصص تعديله.
في
OnSceneGUI()
قبل
EditMesh()
أضف ما يلي:
mesh = target as MeshStudy; Debug.Log("Custom editor is running");
شرح الكود: تحتوي فئة
Editor
على متغير
target
قياسي.
target
هنا هو التحويل إلى
MeshStudy
. الآن سوف يرسم المحرر المخصص جميع GameObjects في نافذة المشهد و
MeshStudy.cs المرفقة بها. تسمح لك إضافة رسائل تصحيح الأخطاء بالتحقق في وحدة التحكم من أن المحرر المخصص يعمل بالفعل.
احفظ الملف وارجع إلى الوحدة. انتقل إلى مجلد
البرامج النصية واسحب
MeshStudy.cs إلى
المكعب GameObject في
التسلسل الهرمي لإرفاقه.
الآن يجب عرض الرسالة "محرر مخصص قيد التشغيل" في وحدة التحكم ، وهذا يعني أننا فعلنا كل شيء بشكل صحيح! يمكنك حذف رسالة تصحيح الأخطاء بحيث لا تزعجنا في وحدة التحكم.
الاستنساخ وإلقاء الشبكة
عند العمل مع شبكة ثلاثية الأبعاد في وضع التحرير باستخدام المحرر المخصص ، احرص على عدم استبدال شبكة الوحدة الافتراضية. إذا حدث ذلك ، فسيتعين عليك إعادة تشغيل الوحدة.
لنسخ الشبكة بأمان دون الكتابة فوق النموذج الأصلي ، قم بإنشاء نسخة من الشبكة من خاصية
MeshFilter.sharedmesh
وقم بتعيينها لمرشح الشبكة مرة أخرى.
للقيام بذلك ، انقر نقرًا مزدوجًا فوق
MeshStudy.cs في مجلد
البرامج النصية لفتح الملف في محرر التعليمات البرمجية. يرث هذا البرنامج النصي من فئة
MonoBehaviour
، ولا يتم تنفيذ وظيفته
Start()
في وضع التحرير.
في
MeshStudy.cs ، قبل بدء فئة
MeshStudy
أضف ما يلي:
[ExecuteInEditMode]
شرح الكود: بعد إضافة هذه السمة ، سيتم تنفيذ وظيفة
Start()
في وضع التشغيل وفي وضع التحرير. الآن يمكننا أولاً إنشاء كائن الشبكة واستنساخه.
في
InitMesh()
أضف التعليمات البرمجية التالية:
oMeshFilter = GetComponent<MeshFilter>(); oMesh = oMeshFilter.sharedMesh;
شرح الكود:
- الحصول على شبكة
oMesh
الأصلية من مكون MeshFilter
. - نسخ
cMesh
إلى cMesh
شبكة جديد. - يعين مرشح شبكة الشبكة المنسوخ مرة أخرى.
- تحديث المتغيرات المحلية.
احفظ الملف وارجع إلى الوحدة. يجب عرض الرسالة "Init & Cloned" في وحدة تحكم التصحيح. حدد GameObject
Cube
في
التسلسل الهرمي وتحقق من خصائصه في
المفتش . يجب أن يعرض "
تصفية الشبكة" أصل شبكة يسمى
استنساخ . عظيم! هذا يعني أننا نجحنا في استنساخ الشبكة.
في مجلد Editor ، انتقل إلى
MeshInspector.cs . في
OnInspectorGUI()
، بعد السطر الثاني من التعليمات البرمجية ، أضف ما يلي:
if (GUILayout.Button("Reset"))
شرح الكود:
- يرسم هذا الرمز زر إعادة الضبط في المفتش .
- عند الضغط عليه ، فإنه يستدعي وظيفة
Reset()
في MeshStudy.cs .
احفظ الملف وافتح
MeshStudy.cs وأضف الكود التالي إلى وظيفة
Reset()
:
if (cMesh != null && oMesh != null)
شرح الكود:
- التحقق من وجود المصدر وشبكة مستنسخة.
- إعادة
cMesh
إلى الشبكة الأصلية. - التعيين إلى
cMesh
oMeshFilter
. - تحديث المتغيرات المحلية.
احفظ الملف وارجع إلى الوحدة. في
المفتش ، انقر على زر
اختبار التحرير لتشويه شبكة المكعب. بعد ذلك ، انقر فوق زر
إعادة الضبط ؛ يجب أن يعود المكعب إلى شكله الأصلي.
شرح القمم والمثلثات في الوحدة
تتكون الشبكة من القمم المتصلة بحواف مثلثات. تحدد المثلثات الشكل الأساسي للكائن.
فئة الشبكة:
- يتم تخزين القمم
Vector3
من قيم Vector3
. - يتم تخزين المثلثات كمصفوفة صحيحة تتوافق مع مؤشرات مجموعة القمة.
بمعنى ، في شبكة رباعية بسيطة تتكون من أربعة رؤوس ومثلثين ، ستبدو بيانات الشبكة كما يلي:
رسم خرائط الرأس
هنا نريد عرض رؤوس المكعب كنقاط زرقاء.
في
MeshInspector.cs سنذهب إلى وظيفة
EditMesh()
ونضيف ما يلي:
handleTransform = mesh.transform;
شرح الكود:
- يحصل
handleTransform
على قيم التحويل من mesh
. - يحصل
handleRotation
على وضع التدوير للمفصل الحالي. - اجتياز رؤوس الشبكة وارسم النقاط باستخدام
ShowPoint()
.
في
ShowPoint()
، مباشرةً بعد
//draw dot
، أضف ما يلي:
Vector3 point = handleTransform.TransformPoint(mesh.vertices[index]);
شرح الكود: هذا الخط يحول الموقع المحلي للرأس إلى إحداثيات في الفضاء العالمي.
في نفس الوظيفة ، في كتلة
if
، بعد سطر التعليمات البرمجية الذي تمت إضافته للتو ، أضف ما يلي:
Handles.color = Color.blue; point = Handles.FreeMoveHandle(point, handleRotation, mesh.handleSize, Vector3.zero, Handles.DotHandleCap);
شرح الكود:
- يضبط لون النقطة وحجمها
Handles
باستخدام فئة المساعد Handles
. Handles.FreeMoveHandle()
ينشئ مناور حركة غير محدود يبسط عملية السحب والإفلات ، وهو أمر مفيد لنا في القسم التالي.
احفظ الملف وارجع إلى الوحدة. تحقق من خاصية المكعب في
المفتش وتأكد من تمكين الخيار
Move Vertex Point . يجب أن ترى الآن أن الشبكة على الشاشة مميزة بالعديد من النقاط الزرقاء. ها هم - قمم شبكة المكعب! حاول القيام بذلك مع كائنات ثلاثية الأبعاد أخرى ولاحظ النتائج.
تحريك قمة واحدة
لنبدأ بالخطوة الأبسط للتلاعب بالشبكة - تحريك قمة واحدة.
انتقل إلى
MeshInspector.cs . داخل
ShowPoint()
، مباشرة بعد
//drag
التعليق مباشرة قبل أقواس الإغلاق للكتلة
if
، أضف ما يلي:
if (GUI.changed)
شرح الكود:
GUI.changed
جميع التغييرات التي تحدث مع النقاط ، ويعمل بشكل جيد مع Handles.FreeMoveHandle()
للتعرف على عملية السحب والإفلات.- بالنسبة
mesh.DoAction()
القابل للسحب ، تتلقى الدالة mesh.DoAction()
الفهرس وقيم التحويل كمعلمات. نظرًا لأن قيم تحويل الرأس في الفضاء العالمي ، فإننا نحولها إلى مساحة محلية باستخدام InverseTransformPoint()
.
احفظ ملف البرنامج النصي
وانتقل إلى
MeshStudy.cs . في
DoAction()
، بعد أقواس الفتح ، أضف ما يلي:
PullOneVertex(index, localPos);
ثم أضف ما يلي إلى
PullOneVertex()
:
vertices[index] = newPos;
شرح الكود:
- نقوم بتحديث قمة الهدف بالقيمة
newPos
. cMesh.vertices
قيم قمة محدثة مرة أخرى إلى cMesh.vertices
.- في
RecalculateNormals()
بإعادة حساب الشبكة وإعادة رسمها بحيث تتطابق مع التغييرات.
احفظ الملف وارجع إلى الوحدة. حاول سحب النقاط على المكعب. هل رأيت شبكة مكسورة؟
يبدو أن بعض القمم لها نفس الوضع ، لذلك عندما نسحب واحدة فقط ، تبقى القمم المتبقية خلفها ، وتتكسر الشبكة. في القسم التالي ، سنقوم بإصلاح هذه المشكلة.
إيجاد جميع القمم المتشابهة
بصريا ، تتكون شبكة المكعب من ثمانية قمم وستة جوانب و 12 مثلثات. دعونا نتحقق مما إذا كان الأمر كذلك.
افتح
MeshStudy.cs ،
وألق نظرة أمام الدالة
Start()
وابحث عن متغير
vertices
. سنرى ما يلي:
[HideInInspector] public Vector3[] vertices;
شرح الكود:
[HideInInspector]
يخفي متغير مشترك من نافذة
المفتش .
التعليق على هذه السمة:
ملاحظة: يساعد إخفاء قيم الذروة [HideInInspector]
شبكات أكثر تعقيدًا ثلاثية الأبعاد. نظرًا لأن حجم صفيف الرأس يمكن أن يصل إلى آلاف العناصر ، فقد يؤدي ذلك إلى تثبيط الوحدة عند محاولة عرض قيمة الصفيف في المفتش.
احفظ الملف وارجع إلى الوحدة. انتقل إلى
المفتش . الآن ، تحت مكون البرنامج النصي
لدراسة شبكة ، ظهرت خاصية
القمم . انقر على أيقونة السهم المجاورة لها ؛ حتى تقوم
Vector3
مجموعة عناصر
Vector3
.
يمكنك أن ترى أن حجم المصفوفة هو 24 ، أي أن القمم لها نفس الموضع! قبل المتابعة ، تأكد من عدم
[HideInInspector]
.
لماذا يوجد 24 قمة؟هناك العديد من النظريات حول هذا الموضوع. لكن أبسط إجابة هي: المكعب له ستة جوانب ، وكل جانب يتكون من أربعة قمم تشكل مستوى.
لذلك ، يكون الحساب كما يلي: 6 × 4 = 24 قمة.
يمكنك البحث عن إجابات أخرى. ولكن في الوقت الحالي ، من السهل معرفة أن بعض الشبكات سيكون لها رؤوس لها نفس الوضع.
في
MeshStudy.cs ، استبدل جميع التعليمات البرمجية الموجودة داخل الدالة
DoAction()
بما يلي:
PullSimilarVertices(index, localPos);
دعنا
PullSimilarVertices()
إلى وظيفة
PullSimilarVertices()
وإضافة ما يلي:
Vector3 targetVertexPos = vertices[index];
شرح الكود:
- نحصل على موضع قمة الهدف ، والتي سيتم استخدامها كوسيطة
FindRelatedVertices()
. - تُرجع هذه الطريقة قائمة الفهارس (المقابلة للقمم) التي لها نفس موضع الرأس المستهدف.
newPos
الحلقة القائمة بالكامل newPos
القمم المقابلة لـ newPos
.cMesh.vertices
vertices
المحدثة مرة أخرى إلى cMesh.vertices
. ثم نسمي RecalculateNormals()
لإعادة رسم الشبكة بالقيم الجديدة.
احفظ الملف وارجع إلى الوحدة. اسحب أي من القمم ؛ الآن يجب أن تحتفظ الشبكة بشكلها ولا تنهار.
الآن بعد أن أكملنا الخطوة الأولى في معالجة الشبكات ، احفظ المشهد وانتقل إلى القسم التالي.
معالجة شبكة
في هذا القسم ، ستتعلم كيفية معالجة الشبكات في الوقت الفعلي. هناك العديد من الطرق ، ولكن في هذا البرنامج التعليمي سنلقي نظرة على أبسط نوع من معالجة الشبكة ، أي تحريك رؤوس الشبكات التي تم إنشاؤها سابقًا.
جمع الفهارس المختارة
لنبدأ باختيار الذروات التي سننقلها في الوقت الفعلي.
افتح Scene
02 Create Heart Mesh من مجلد
Scenes . في نافذة المشهد ، سترى كرة حمراء. حدد
المجال في
التسلسل الهرمي وانتقل إلى
المفتش . سترى أن مكون البرنامج النصي
Heart Mesh مرفق بالكائن.
نحتاج الآن إلى البرنامج النصي Editor لهذا الكائن لعرض رؤوس الشبكة في نافذة Scene. انتقل إلى مجلد
Editor وانقر نقرًا مزدوجًا فوق
HeartMeshInspector.cs .
في
ShowHandle()
، داخل كتلة
if
، أضف ما يلي:
Handles.color = Color.blue; if (Handles.Button(point, handleRotation, mesh.pickSize, mesh.pickSize, Handles.DotHandleCap))
شرح الكود:
- يضبط ويعرض رؤوس الشبكة كنوع
Handles.Button
. - عند النقر فوقه ، فإنه يضيف الفهرس المحدد إلى قائمة الضغط على
mesh.selectedIndices
.
في
OnInspectorGUI()
، قبل قوس الإغلاق ، أضف ما يلي:
if (GUILayout.Button("Clear Selected Vertices")) { mesh.ClearAllData(); }
شرح الكود: هذه هي الطريقة التي نضيف بها زر إعادة الضبط إلى
المفتش لاستدعاء
mesh.ClearAllData()
.
احفظ الملف وافتح
HeartMesh.cs من مجلد
البرامج النصية . في دالة
ClearAllData()
، أضف ما يلي:
selectedIndices = new List<int>(); targetIndex = 0; targetVertex = Vector3.zero;
شرح الكود: يمحو الكود القيم الموجودة في
targetIndex
selectedIndices
و
targetIndex
. كما يعيد تعيين
targetVertex
.
احفظ الملف وارجع إلى الوحدة. حدد
المجال وانتقل إلى
المفتش لمكون البرنامج النصي
HeartMesh . قم بتوسيع
المؤشرات المحددة بالضغط على أيقونة السهم المجاورة لها. سيسمح لنا هذا بتتبع كل قمة يتم إضافتها إلى القائمة.
تمكين
وضع التعديل باستخدام مربع الاختيار المجاور له. ونتيجة لذلك ، سيتم رسم رؤوس الشبكة في نافذة المشهد. النقر على النقاط الزرقاء في
المؤشرات المحددة يجب أن يغير القيم وفقًا لذلك. اختبر أيضًا زر
مسح القمم المحددة للتأكد من أنه يمسح جميع القيم.
ملاحظة: في
المفتش المخصص المعدل ، لدينا خيار إظهار / إخفاء معالج التحويل باستخدام
إظهار مقبض التحويل . لذلك لا داعي للذعر إذا لم تجد معالج التحويل في مشاهد أخرى! قم بتشغيله قبل الخروج.
تحويل المجال إلى قلب
يتكون تغيير رؤوس الشبكات في الوقت الفعلي بشكل أساسي من ثلاث خطوات:
- انسخ رؤوس الشبكة الحالية (قبل الرسم المتحرك) إلى
mVertices
. mVertices
الحسابات وتغيير القيم في mVertices
.- قم بتحديث رؤوس الشبكة الحالية باستخدام
mVertices
عند التغيير في كل خطوة ودع الوحدة تقوم بحساب القيم الطبيعية تلقائيًا.
افتح
HeartMesh.cs والمتغيرات التالية قبل وظيفة
Start()
:
public float radiusofeffect = 0.3f;
شرح الكود:
- نصف قطر المنطقة المتضررة من قمة الهدف.
- قوة السحب.
- مدة الرسوم المتحركة.
- الفهرس الحالي لقائمة المؤشرات
selectedIndices
.
في دالة
Init()
، قبل كتلة
if
، أضف ما يلي:
currentIndex = 0;
شرح الكود: في بداية اللعبة ،
currentIndex
على 0 ، وهو أول فهرس لقائمة المؤشرات
selectedIndices
.
في نفس دالة
Init()
، قبل قوس الإغلاق للكتلة
else
، أضف ما يلي:
StartDisplacement();
شرح الكود: قم بتشغيل
StartDisplacement()
إذا كان
isEditMode
خطأ.
داخل
StartDisplacement()
، أضف ما يلي:
targetVertex = oVertices[selectedIndices[currentIndex]];
شرح الكود:
- حدد
targetVertex
لبدء الرسوم المتحركة. - قم بتعيين وقت البدء وتغيير قيمة
isAnimate
إلى true.
بعد وظيفة
StartDisplacement()
، قم بإنشاء وظيفة
FixedUpdate()
بالكود التالي:
void FixedUpdate()
شرح الكود:
- يتم تنفيذ الوظيفة
FixedUpdate()
في حلقة FPS ثابتة. - إذا كانت
isAnimate
خاطئة ، isAnimate
بتخطي الرمز التالي. - تغيير الرسوم المتحركة
runtime
. - إذا كان
runtime
ضمن duration
، فإننا نحصل على إحداثيات العالم من targetVertex
و DisplaceVertices()
، والتي تغطي الرأس المستهدف pullvalue
و radiusofeffect
. - خلاف ذلك ، انتهى الوقت. أضف واحدًا إلى
currentIndex
. - تحقق مما إذا كان
currentIndex
بين currentIndex
selectedIndices
. انتقل إلى القمة التالية في القائمة باستخدام StartDisplacement()
. - خلاف ذلك ، في نهاية القائمة ، قم بتغيير بيانات
oMesh
إلى الشبكة الحالية isAnimate
إلى false لإيقاف الرسوم المتحركة.
في
DisplaceVertices()
أضف ما يلي:
Vector3 currentVertexPos = Vector3.zero; float sqrRadius = radius * radius;
شرح الكود:
- مربع نصف القطر.
- نحن ندور عبر كل قمة للشبكة.
sqrMagnitude
بين currentVertexPos
و targetVertexPos
.- إذا تجاوز
sqrRadius
، فانتقل إلى القمة التالية. - خلاف ذلك ، استمر في تحديد قيمة
falloff
، والتي تعتمد على distance
القمة الحالية من نقطة مركز النطاق. Vector3
موضع Vector3
الجديد Vector3
بتطبيق تحويله على قمة الرأس الحالية.- عند الخروج من الحلقة ، نقوم بتعيين قيم
mVertices
تغييرها إلى mVertices
، mVertices
الوحدة على إعادة حساب القيم الطبيعية.
مصدر تكنولوجيا Falloff
يتم أخذ الصيغة الأصلية من ملف حزمة الأصول الأمثلة الإجرائية ، والذي يمكن تنزيله مجانًا من Unity Asset Store.
احفظ الملف وارجع إلى الوحدة. حدد
المجال ، انتقل إلى مكون
HeartMesh وحاول إضافة بعض القمم إلى خاصية
المؤشرات المحددة . قم بتعطيل
وضع Is Edit وانقر فوق
Play لإلقاء نظرة على نتيجة عملك.
اختبر
قيم Radiusofeffect و
Pullvalue و
Duration للحصول على نتائج مختلفة. عندما تكون جاهزًا ، قم بتغيير الإعدادات بما يتوافق مع لقطة الشاشة أدناه.
انقر فوق
تشغيل . هل تحول مجالك إلى قلب؟
مبروك! في القسم التالي ، سنحفظ الشبكة كإعداد مسبق للاستخدام المستقبلي.
حفظ الشبكة في الوقت الحقيقي
لحفظ شبكة إجرائية على شكل قلب في وضع التشغيل ، تحتاج إلى إعداد مسبقة يكون طفلها كائنًا ثلاثي الأبعاد ، ثم استبدال أصل شبكته بأخرى جديدة باستخدام برنامج نصي.
في نافذة
Project ، ابحث عن
CustomHeart في مجلد
Prefabs . انقر فوق رمز السهم لتوسيع محتوياته وحدد
الطفل . ترى الآن كائن Sphere في نافذة معاينة
المفتش . هذا هو الجاهزة التي ستقوم بتخزين البيانات للشبكة الجديدة.
افتح
HeartMeshInspector.cs . داخل
OnInspectorGUI()
، قبل قوس الإغلاق ، أضف ما يلي:
if (!mesh.isEditMode && mesh.isMeshReady) { string path = "Assets/Prefabs/CustomHeart.prefab";
شرح الكود:
- لتعيين
path
إلى المسار إلى كائن CustomHeart. - إنشاء كائنين من الإعداد المسبق CustomHeart ، أحدهما لإنشاء مثيل مثل GameObject (
pfObj
) ، والثاني كروابط ( pfRef
). - إنشاء مثيل لأصل شبكة
pfMesh
. إذا لم يتم العثور عليه ، ينشئ شبكة جديدة ، وإلا فإنه ينظف البيانات الموجودة. pfMesh
ببيانات شبكة جديدة ، ثم يضيفها كأصل إلى CustomHeart .
- يملأ أصل شبكة في
gameObj
بقيمة pfMesh
. - يستبدل CustomHeart بـ
gameObj
مطابقة الاتصالات الموجودة مسبقًا. - يدمر على الفور
gameObj
احفظ الملف
وانتقل إلى
HeartMesh.cs . في طريقة
SaveMesh()
العامة ، بعد إنشاء مثيل
nMesh
أضف ما يلي:
nMesh.name = "HeartMesh"; nMesh.vertices = oMesh.vertices; nMesh.triangles = oMesh.triangles; nMesh.normals = oMesh.normals;
شرح الرمز: إرجاع أصل شبكة مع قيم من شبكة على شكل قلب.
احفظ الملف وارجع إلى الوحدة. انقر فوق
تشغيل . بعد اكتمال الرسم المتحرك ، سيظهر زر
Save Mesh في
المفتش . انقر فوق الزر لحفظ الشبكة الجديدة ، ثم أوقف المشغل.
انتقل إلى مجلد
Prefabs وانظر إلى CustomHeart
الجاهزة . يجب أن ترى أنه الآن في كائن CustomHeart
الجاهزة ، توجد شبكة جديدة تمامًا على شكل قلب.
عمل رائع!ضع كل ذلك معًا
في المشهد السابق ، استخدمت الدالة
DisplaceVertices()
صيغة Falloff لتحديد قوة السحب التي تم تطبيقها على كل قمة داخل نصف قطر معين. تعتمد نقطة "السقوط" ، التي تبدأ عندها قوة السحب في الانخفاض ، على نوع السقوط المستخدم: الخطي أو الغوسي أو الإبرة. ينتج كل نوع نتائج مختلفة في الشبكة.
في هذا القسم ، سننظر في طريقة أخرى للتعامل مع القمم: باستخدام منحنى معين. مع الأخذ في الاعتبار أن السرعة تساوي المسافة مقسومة على الوقت (d = (v / t)) ، يمكننا تحديد موضع المتجه ، بالإشارة إلى المسافة مقسومة على الوقت.
باستخدام طريقة المنحنى
احفظ المشهد الحالي وافتح
03 Customize Heart Mesh من مجلد
Scenes . سترى نسخة
هرمية من الإعداد CustomHeart. انقر فوق رمز السهم المجاور له لتوسيع محتوياته وحدد
الطفل .
عرض خصائصه في
المفتش .
Mesh Filter Heart Mesh .
Child Custom Heart .
HeartMesh clone .
CustomHeart.cs Scripts .
Start()
:
public enum CurveType { Curve1, Curve2 } public CurveType curveType; Curve curve;
: (enum)
CurveType
,
Inspector .
CurveType1()
:
Vector3[] curvepoints = new Vector3[3];
:
- . .
- نقوم بإنشاء المنحنى الأول بمساعدة
Curve()
وتعيين قيمه curve
. يمكن عرض المنحنى المرسوم في المعاينة إذا حددت true كمعلمة أخيرة.
انتقل إلى CurveType2()
وقم بإضافة ما يلي: Vector3[] curvepoints = new Vector3[3];
شرح الكود:- حدد النقاط للمنحنى الثاني.
- نقوم بإنشاء المنحنى الثاني
Curve()
وتعيين قيمه curve
. يمكن عرض المنحنى المرسوم في المعاينة إذا حددت true كمعلمة أخيرة.
ب StartDisplacement()
، قبل قوس الإغلاق ، يضاف ما يلي: if (curveType == CurveType.Curve1) { CurveType1(); } else if (curveType == CurveType.Curve2) { CurveType2(); }
شرح الكود: هنا نتحقق من الخيار الذي حدده المستخدم curveType
وننشئه وفقًا لذلك curve
.ب DisplaceVertices()
، داخل بيان الحلقة for
قبل أقواس الإغلاق ، أضف ما يلي: float increment = curve.GetPoint(distance).y * force;
شرح الكود:distance
y
force
, increment
.Vector3
Transform.
Unity.
CustomHeart Child . ,
Curve Type .
Edit Type Add Indices Remove Indices , .
, :
Curve Type Curve1 , ,
Edit Type None Play . , . , , . ,
Curve Type .
هذا كل شيء!
Clear Selected Vertices ,
Selected Indices . , , , :
?
.
! ,
« Unity» .
, , .
Catlike Coding , .