تم تخصيص منشور المدونة هذا بالكامل لنظام الرسوم المتحركة الخاص بي ، وهو مليء بالنصائح المفيدة ومقتطفات الكود.
على مدى الشهرين الماضيين ، خلقت ما يصل إلى 9 تصرفات جديدة للاعبين (مثل أشياء مضحكة مثل الحجب بالدرع وتفادي القفز والأسلحة) و 17 عنصرًا جديدًا يمكن ارتداؤها و 3 مجموعات من الدروع (اللوحة والحرير والجلود) و 6 أنواع من قصات الشعر. لقد انتهيت أيضًا من إنشاء جميع أدوات التشغيل الآلي والأدوات ، لذلك كل شيء مستخدم بالفعل في اللعبة. في المقال سأقول كيف حققت هذا!
آمل أن تكون هذه المعلومات مفيدة وتثبت أنه ليس من الضروري أن تكون عبقريًا من أجل إنشاء هذه الأدوات / التشغيل الآلي بشكل مستقل.وصف قصير
في البداية ، أردت التحقق مما إذا كان من الممكن الجمع بين العفاريت المتراكبة على بعضها البعض مع الرسوم المتحركة المتزامنة لإنشاء شخصية نمطية مع تسريحات الشعر القابلة للاستبدال والمعدات والبنود التي يمكن ارتداؤها. هل من الممكن الجمع بين الرسوم المتحركة المرسومة باليد بكسل مع شخصية قابلة للتخصيص حقا.
بالطبع ، يتم استخدام هذه الوظائف بنشاط في الألعاب ثلاثية الأبعاد والثنائية الأبعاد مع العفاريت المقدمة مسبقًا أو في الألعاب ثنائية الأبعاد مع الرسوم المتحركة الهيكلية ، ولكن على حد علمي ، لا توجد العديد من الألعاب التي تجمع بين الرسوم المتحركة التي تم إنشاؤها يدويًا والشخصيات المعيارية (عادةً لأن العملية تتضح أنها رتابة جدا).
اكتشفت هذا GIF القديم من أول شهر لي مع الوحدة. في الواقع ، كانت هذه العفاريت المعيارية واحدة من تجاربي الأولى في تطوير اللعبة!لقد قمت بإنشاء نموذج أولي باستخدام نظام الرسوم المتحركة Unity ، ثم قمت بإضافة قميص واحد وزوج واحد من السراويل وتصفيفة شعر وثلاثة عناصر لاختبار المفهوم. هذا يتطلب 26 الرسوم المتحركة منفصلة.
في ذلك الوقت ، قمت بإنشاء كل الرسوم المتحركة الخاصة بي في Photoshop ولم أكن مهتمًا بأتمتة العملية ، لذلك كانت مملة للغاية. ثم فكرت: "إذن ، الفكرة الأساسية عملت ، وسأضيف لاحقًا رسوم متحركة ومعدات جديدة." اتضح أن "لاحقًا" بعد بضع سنوات.
في شهر مارس من هذا العام ، قمت بتصميم تصميم كمية كبيرة من الدروع (انظر منصبي السابق) ، ولاحظت كيف يمكن جعل هذه العملية أكثر ملاءمة. واصلت تأجيل التنفيذ ، لأنه حتى مع الأتمتة ، كنت متوترة من عدم عمل أي شيء.
توقعت أنه سيتعين علي التخلي عن تخصيص الشخصية وإنشاء الشخصية الرئيسية الوحيدة ، كما في معظم الألعاب باستخدام الرسوم المتحركة اليدوية. لكن لدي خطة عمل ، وقد حان الوقت للتحقق مما إذا كان بإمكاني هزيمة هذا الوحش!
المفسد: كل شيء تحول كبير. أدناه سوف تكشف أسرار ***نظام العفريت وحدات
تعرف على حدودك
في السابق ، أجريت العديد من اختبارات الفن والتحكم في الوقت لمعرفة المدة التي يمكن أن يستغرقها هذا العمل وما إذا كان مستوى الجودة المتماثل سيكون قابلاً للتحقيق بالنسبة لي.
كتبت كل أفكاري للرسوم المتحركة ، ووضعتها في جدول بيانات ، ورتبتها وفقًا لمعايير مختلفة ، مثل الفائدة والجمال والاستخدام المتكرر. لدهشتي ، كان الأول في هذه القائمة هو الرسوم المتحركة المدلى بها لهذا البند (الجرعات ، القنابل ، السكاكين ، الفؤوس ، الكرة).
لقد توصلت إلى درجة عددية لكل الرسوم المتحركة وتركت كل شيء مع الأداء الضعيف. في البداية ، خططت لإنشاء 6 مجموعات من المدرعات ، لكن سرعان ما أدركت أنه كان أكثر من اللازم ، وطردت ثلاثة أنواع.
تبين أن جانب تتبع الوقت أمر مهم للغاية ، وأنا أوصي بشدة باستخدامه للإجابة على أسئلة مثل: "كم عدد الأعداء الذين يمكنني صنعهم في اللعبة؟". بعد بضعة اختبارات فقط ، تمكنت من استنباط تقدير دقيق إلى حد ما. مع مزيد من العمل على الرسوم المتحركة ، واصلت متابعة الوقت ومراجعة توقعاتي.
سوف أشارك نسخة من مجلة العمل الخاصة بي خلال الشهرين الماضيين. يرجى ملاحظة أن هذه المرة بالإضافة إلى عملي المعتاد ، حيث أقضي 30 ساعة في الأسبوع:https://docs.google.com/spreadsheets/d/1Nbr7lujZTB4pWMsuedVcgBYS6n5V-rHrk1PxeGxr6Ck/edit؟usp=sharingII. تغيير لوحة لمستقبل أكثر إشراقا
باستخدام الألوان في تصميم sprite بحكمة ، يمكنك رسم نقش واحد وإنشاء العديد من الأشكال المختلفة عن طريق تغيير اللوحة. لا يمكنك تغيير الألوان فحسب ، بل يمكنك أيضًا إنشاء عناصر متنوعة وإيقاف (على سبيل المثال ، استبدال الألوان بالشفافية).
كل مجموعة من الدروع لديها 3 أشكال ، ومن خلال خلط الأجزاء العلوية والسفلية ، يمكنك الحصول على العديد من المجموعات. أخطط لتطبيق نظام يمكنك من خلاله جمع مجموعة واحدة من الدروع لظهور الشخصية ، وآخر لخصائصه (كما في Terraria).
في هذه العملية ، فوجئت بسرور بالمجموعات الغريبة المكتشفة. إذا قمت بتوصيل سطح اللوحة بأسفل حرير ، فيمكنك الحصول على شيء بأسلوب مجسم الحرب.من الأفضل تغيير اللوحات باستخدام الألوان التي ترمز القيمة في العفريت بحيث يمكنك اصطحابها لاحقًا للعثور على اللون الحقيقي من اللوحة. أعلم أنني أبسّط بعض الشيء ، فإليك مقطع فيديو لتبدأ به:
لن أشرح كل شيء بالتفصيل ، لكن بدلاً من ذلك سأتحدث عن طرق لتطبيق هذه التقنية في الوحدة ، وإيجابياتهم وسلبياتهم.
1. ابحث عن نسيج لكل لوحة
هذه هي أفضل استراتيجية لإنشاء أشكال مختلفة من الأعداء والخلفيات وكل ذلك عندما يكون للعديد من العفاريت نفس اللوحة / المواد. لا يمكن تجميع المواد المختلفة في مجموعات ، حتى لو كانت تستخدم نفس العفريت / الأطلس. يعتبر العمل باستخدام مواد مؤلمة للغاية ، ولكن يمكنك تغيير اللوحات في الوقت الفعلي عن طريق استبدال المواد باستخدام SpriteRenderer.sharedMaterial.SetTexture أو MaterialPropertyBlock إذا كنت بحاجة إلى لوحات مختلفة لكل مثيل من المواد. فيما يلي مثال لوظيفة شظية التظليل:
sampler2D _MainTex; sampler2D _PaletteTex; float4 _PaletteTex_TexelSize; half4 frag(v2f input) : SV_TARGET { half4 lookup = tex2D(_MainTex, input.uv); half4 color = tex2D(_PaletteTex, half2(lookup.r * (_PaletteTex_TexelSize.x / 0.00390625f), 0.5)); color.a *= lookup.a; return color * input.color; }
2. مجموعة من الألوان
لقد استقرت على هذا القرار لأنني كنت بحاجة إلى استبدال اللوحات في كل مرة يتغير فيها مظهر الشخصية (على سبيل المثال ، عند وضع العناصر) ، وإنشاء بعض اللوحات بشكل حيوي (لعرض ألوان الشعر ولون البشرة المختار من قبل اللاعب). بدا لي أنه في وقت التشغيل وفي المحرر لهذه الأغراض ، سيكون من الأسهل بكثير العمل مع المصفوفات.
كود:
sampler2D _MainTex; half4 _Colors[32]; half4 frag(v2f input) : SV_TARGET { half4 lookup = tex2D(_MainTex, input.uv); half4 color = _Colors[round(lookup.r * 255)]; color.a *= lookup.a; return color * input.color; }
قدمت ألواح الألوان كنوع ScriptableObject واستخدمت أداة MonoBehaviour لتحريرها. بعد أن عملت لفترة طويلة على تحرير اللوحات في عملية إنشاء الرسوم المتحركة في Aseprite ، أدركت الأدوات التي احتاجتها وكتبت هذه النصوص وفقًا لذلك. إذا كنت تريد كتابة الأداة الخاصة بك لتحرير اللوحات ، فإليك بعض الوظائف التي أوصي بالتأكيد بتنفيذها:
- تحديث اللوحات على المواد المختلفة عند تحرير الألوان لعرض التغييرات في الوقت الحقيقي.
- تعيين أسماء وتغيير ترتيب الألوان في اللوحة (استخدم الحقل لتخزين فهرس الألوان ، وليس ترتيبه في الصفيف).
- حدد وتحرير ألوان متعددة في وقت واحد. (نصيحة: يمكنك نسخ ولصق حقول اللون في الوحدة: فقط اضغط على لون واحد ، انسخ ، انقر فوق لون آخر ، الصق - الآن هي نفسها!)
- تطبيق لون التراكب على لوحة كاملة
- سجل لوحة في الملمس
3. نسيج بحث واحد لجميع لوحات
إذا كنت ترغب في تبديل اللوحات على الطاير ، ولكن في نفس الوقت تحتاج إلى الدفع لتقليل عدد مكالمات السحب ، يمكنك استخدام هذه التقنية. قد يكون مفيدًا لمنصات المحمول ، ولكن استخدامه غير مريح تمامًا.
أولاً ، ستحتاج إلى حزم جميع اللوحات في نسيج واحد كبير. ثم تستخدم اللون المحدد في مكون SpriteRenderer (لون قمة الرأس AKA) لتحديد الخط المراد قراءته من نسيج اللوحة في التظليل. بمعنى ، يتم التحكم في لوحة هذا العفريت من خلال SpriteRenderer.color. لون Vertex هو خاصية SpriteRenderer الوحيدة التي يمكن تغييرها دون كسر الشرط (بشرط أن تكون جميع المواد متشابهة).
في معظم الحالات ، من الأفضل استخدام قناة ألفا للتحكم في الفهرس ، لأنك ربما لن تحتاج إلى مجموعة من العفاريت مع شفافية مختلفة.
كود:
sampler2D _MainTex; sampler2D _PaletteTex; float4 _PaletteTex_TexelSize; half4 frag(v2f input) : SV_TARGET { half4 lookup = tex2D(_MainTex, input.uv); half2 paletteUV = half2( lookup.r * _(PaletteTex_TexelSize.x / 0.00390625f), input.color.a * _(PaletteTex_TexelSize.y / 0.00390625f) ) half4 color = tex2D(_PaletteTex, paletteUV); color.a *= lookup.a; color.rgb *= input.color.rgb; return color; }
عجائب استبدال الألواح وطبقات العفريت. الكثير من المجموعات.III. أتمتة كل شيء واستخدام الأدوات المناسبة.
لتنفيذ هذه الوظيفة ، كانت الأتمتة ضرورية للغاية ، لأنني حصلت على حوالي 300 من الرسوم المتحركة وآلاف العفاريت.
كانت خطوتي الأولى هي إنشاء مصدر لـ Aseprite لإدارة مخطط طبقة العفريت المجنون باستخدام
واجهة سطر أوامر مريحة. هذا مجرد برنامج نصي بيرل يتخطى جميع الطبقات والعلامات في ملف Aseprite الخاص بي ويقوم بتصدير الصور في بنية دليل واسم محددة حتى أتمكن من قراءتها لاحقًا.
ثم كتبت مستوردًا للوحدة. يعرض Aseprite ملف JSON مناسبًا مع بيانات الإطار ، بحيث يمكنك إنشاء أصول رسوم متحركة برمجيًا. تبين أن التعامل مع Aseprite JSON وكتابة نوع البيانات هذا كان مملاً للغاية ، لذا أحضرهم إلى هنا. يمكنك تحميلها بسهولة في Unity باستخدام JsonUtility.FromJson <AespriteData> ، فقط تذكر تشغيل Aseprite باستخدام الخيار - تنسيق "json-array".
كود:
[System.Serializable] public struct AespriteData { [System.Serializable] public struct Size { public int w; public int h; } [System.Serializable] public struct Position { public int x; public int y; public int w; public int h; } [System.Serializable] public struct Frame { public string filename; public Position frame; public bool rotated; public bool trimmed; public Position spriteSourceSize; public Size sourceSize; public int duration; } [System.Serializable] public struct Metadata { public string app; public string version; public string format; public Size size; public string scale; } public Frame[] frames; public Metadata meta; }
على جانب الوحدة ، واجهت مشاكل خطيرة في مكانين: تحميل / تشريح ورقة العفاريت وإنشاء مقطع رسوم متحركة. هناك مثال واضح سيساعدني كثيرًا ، لذلك يوجد هنا مقتطف من الكود من المستورد حتى لا تعاني كثيرًا:
كود:
TextureImporter textureImporter = AssetImporter.GetAtPath(spritePath) as TextureImporter; textureImporter.spriteImportMode = SpriteImportMode.Multiple; SpriteMetaData[] spriteMetaData = new SpriteMetaData[aespriteData.frames.Length];
إذا لم تكن قد فعلت ذلك بعد ، فاصدقني - من السهل جدًا البدء في إنشاء أدواتك الخاصة. أسهل خدعة هي وضع GameObject في المشهد مع MonoBehaviour مرفقة به ، والذي له سمة [ExecuteInEditMode]. أضف زر وأنت جاهز للمعركة! تذكر أن أدواتك الشخصية لا يجب أن تبدو جيدة ، بل يمكن أن تكون نفعية بحتة.
كود:
[ExecuteInEditMode] public class MyCoolTool : MonoBehaviour { public bool button; void Update() { if (button) { button = false; DoThing(); } } }
عند العمل باستخدام sprites ، من السهل تمامًا أتمتة المهام القياسية (على سبيل المثال ، إنشاء مواد لوحة أو استبدال مجموعات الألوان في العديد من ملفات sprite). فيما يلي مثال يمكنك من خلاله البدء في تعلم كيفية تغيير العفاريت.
كود:
string path = "Assets/Whatever/Sprite.png"; Texture2D texture = AssetDatabase.LoadAssetAtPath<Texture2D>(path); TextureImporter textureImporter = AssetImporter.GetAtPath(path) as TextureImporter; if (!textureImporter.isReadable) { textureImporter.isReadable = true; AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate); } Color[] pixels = texture.GetPixels(0, 0, texture.width, texture.height); for (int i = 0; i < pixels.Length; i++) {
كيف أتفوق على مكانيم الفرص: شكوى
بمرور الوقت ، أصبح نظام العفاري المعياري النموذجي الذي أنشأته باستخدام Mecanim أكبر مشكلة عند ترقية Unity ، لأن API كان يتغير باستمرار ولم يكن موثقًا بشكل جيد. في حالة جهاز الحالة البسيط ، سيكون من الحكمة أن تكون قادرًا على الاستعلام عن حالة كل مقطع أو تغيير المقاطع في وقت التشغيل. لكن لا! لأسباب تتعلق بالأداء ، تقوم Unity بتقطيع مقاطع في حالتها وتجبرنا على استخدام نظام إعادة تعريف أخرق لتغييرها.
Mecanim في حد ذاته ليس نظامًا سيئًا ، لكن يبدو لي أنه لا ينجح في تحقيق الميزة الرئيسية المعلنة - البساطة. كانت فكرة المطورين استبدال ما بدا معقدًا ومؤلماً (كتابة نصية) بشيء بسيط (جهاز الحالة المرئية). ولكن:
- يتحول أي جهاز محدود الحجم غير تافهة إلى شبكة متداخلة من العقد والوصلات ، وينتشر منطقها عبر طبقات مختلفة.
- يتم إعاقة حالات الاستخدام البسيطة بواسطة متطلبات النظام المعممة. لتشغيل رسم متحرك واحد أو اثنين ، تحتاج إلى إنشاء وحدة تحكم جديدة وتعيين حالات / انتقالات. بالطبع ، هناك تبذير مفرط للموارد.
- من المضحك أنه نتيجة لذلك ، لا يزال يتعين عليك كتابة التعليمات البرمجية ، لأنه من أجل أن يقوم جهاز الحالة بعمل شيء مثير للاهتمام ، فإنك تحتاج إلى برنامج نصي يستدعي Animator.SetBool وطرق مماثلة.
- للاستخدام المتعدد لجهاز الحالة مع مقاطع أخرى ، تحتاج إلى تكرارها واستبدالها يدويًا. في المستقبل ، سيكون عليك إجراء تغييرات في عدة أماكن.
- إذا كنت ترغب في تغيير ما هو في حالة في وقت التشغيل ، فأنت تواجه مشاكل. الحل هو إما واجهة برمجة تطبيقات غير صالحة أو رسم بياني مجنون به عقدة واحدة لكل رسم متحرك ممكن.
قصة كيف دخل مطورو Firewatch إلى جحيم البرمجة النصية المرئية . الشيء المضحك هو أنه عندما يعرض المتحدث أبسط الأمثلة ، فإنها لا تزال تبدو مجنونة. المتفرجون يئنون حرفيا الساعة 12:41 . أضف تكاليف صيانة ضخمة ، وسوف تفهم لماذا لا أحب بشدة هذا النظام.العديد من هذه المشاكل ليست حتى خطأ مطوري Mecanim ، ولكنها ببساطة نتيجة طبيعية للأفكار غير المتوافقة: لا يمكنك إنشاء نظام بسيط وبسيط في نفس الوقت ، ووصف المنطق باستخدام الصور هو أكثر صعوبة من مجرد الكلمات / الرموز (هل يتذكر أحد مخططات UML؟) . استذكرت جزءًا من تقرير
Zack McClendon في Practice NYC 2018 ، وإذا كان لديك وقت ، أوصي بمشاهدة الفيديو بالكامل!
ومع ذلك ، لقد حظيت بها. يتم دائمًا ضبط البرمجة النصية المرئية بواسطة المهووسين "اكتب محركك الخاص" العدواني الذين لا يفهمون احتياجات الفنان. بالإضافة إلى ذلك ، لا يمكن إنكار أن معظم الشفرة تبدو وكأنها لغة تقنية غير مفهومة.
إذا كنت بالفعل مبرمجًا قليلًا وتجري ألعابًا باستخدام رموز متحركة ، فقد تحتاج إلى التفكير مرتين. عندما بدأت ، كنت متأكدًا من أنه لا يمكنني أبدًا كتابة شيء متعلق بالمحرك أفضل من مطوري Unity.
وانت تعرف ماذا؟ اتضح أن برنامج الرسوم المتحركة sprite هو مجرد برنامج نصي يقوم بتغيير sprite بعد عدد محدد من الثواني. مهما كان الأمر ، لا يزال عليّ أن أكتب نفسي. منذ ذلك الحين أضفت أحداث رسوم متحركة ووظائف أخرى إلى مشروعي المحدد ، لكن الإصدار الأساسي الذي كتبته في نصف يوم يغطي 90٪ من احتياجاتي. يتكون من 120 سطرًا ويمكن تنزيله مجانًا من هنا:
https://pastebin.com/m9Lfmd94 . شكرا لك على قراءة مقالتي. اراك قريبا!