كيف أعدنا تصور العمل مع المشاهد في الوحدة

الوحدة ، كمحرك ، لها عدد من العيوب ، والتي بفضل إمكانيات التخصيص وأدوات إنشاء الشفرات ، يمكن حلها.

سأخبرك الآن كيف كتبنا مكونًا إضافيًا لـ Unity بناءً على مشاريع ما بعد المعالجة ومولد كود CodeDom.

مشكلة

في Unity ، يتم تحميل المشاهد من خلال معرف سلسلة. إنه غير مستقر ، مما يعني أنه يمكن تغييره بسهولة دون عواقب واضحة. على سبيل المثال ، عندما تعيد تسمية مشهد ما ، فإن كل شيء سوف يطير ، لكن سيتم الكشف عنه فقط في نهاية مرحلة التنفيذ.

تظهر المشكلة بسرعة في المشاهد المستخدمة بشكل متكرر ، ولكن قد يكون من الصعب اكتشافها عندما يتعلق الأمر بالمشاهد المضافة الصغيرة أو المشاهد التي نادرًا ما يتم استخدامها.

القرار

عند إضافة مشهد إلى مشروع ، يتم إنشاء فئة بنفس الاسم باستخدام طريقة التحميل.

إذا أضفنا مشهد قائمة ، فسيتم إنشاء فئة القائمة في المشروع وفي المستقبل يمكننا بدء المشهد على النحو التالي:

Menu.Load();

نعم ، الطريقة الثابتة ليست أفضل تخطيط. لكن بدا لي تصميمًا مقتضبًا ومريحًا. يحدث الإنشاء تلقائيًا ، الكود المصدري لهذه الفئة:

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.42000
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace IJunior.TypedScenes
{   
    public class Menu : TypedScene
    {
        private const string GUID = "a3ac3ba38209c7744b9e05301cbfa453";
        
        public static void Load()
        {
            LoadScene(GUID);
        }
    }
}

بطريقة ودية ، يجب أن تكون الفئة ثابتة ، حيث لا يُفترض أن يتم إنشاء مثيل لها منها. هذا خطأ سنصلحه. كما ترون من هذا الجزء ، الكود لا نتمسك بالاسم ، ولكن بالمشهد GUID ، وهو أكثر موثوقية. تبدو الفئة الأساسية نفسها كما يلي:

namespace IJunior.TypedScenes
{
    public abstract class TypedScene
    {
        protected static void LoadScene(string guid)
        {
            var path = AssetDatabase.GUIDToAssetPath(guid);
            SceneManager.LoadScene(path);
        }

        protected static void LoadScene<T>(string guid, T argument)
        {
            var path = AssetDatabase.GUIDToAssetPath(guid);

            UnityAction<Scene, Scene> handler = null;
            handler = (from, to) =>
            {
                if (to.name == Path.GetFileNameWithoutExtension(path))
                {
                    SceneManager.activeSceneChanged -= handler;
                    HandleSceneLoaders(argument);
                }
            };

            SceneManager.activeSceneChanged += handler;
            SceneManager.LoadScene(path);
        }

        private static void HandleSceneLoaders<T>(T loadingModel)
        {
            foreach (var rootObjects in SceneManager.GetActiveScene().GetRootGameObjects())
            {
                foreach (var handler in rootObjects.GetComponentsInChildren<ISceneLoadHandler<T>>())
                {
                    handler.OnSceneLoaded(loadingModel);
                }
            }
        }
    }
}

- .

- ( , ), .

, .

, Game , .

.

using IJunior.TypedScenes;
using System.Collections.Generic;
using UnityEngine;

public class GameLoadHandler : MonoBehaviour, ISceneLoadHandler<IEnumerable<Player>>
{
    public void OnSceneLoaded(IEnumerable<Player> players)
    {
        foreach (var player in players)
        {
            //make avatars
        }
    }
}

, .

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.42000
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace IJunior.TypedScenes
{
    public class Game : TypedScene
    {
        private const string GUID = "976661b7057d74e41abb6eb799024ada";
        
        public static void Load(System.Collections.Generic.IEnumerable<Player> argument)
        {
            LoadScene(GUID, argument);
        }
    }
}

. .. N , N . - .

, , , .

N?

YouTube .

. , , , .

, ?

. :

public class GameArguments
{
    public IEnumerable<Player> Players { get; set; }
}

, , , .

, : , . , .

ID .

PlayerPerfs

. , PlayerPrefs . , , .

ASPNet

- View ASPNet Core. ViewData ViewModel. Unity - .

Unity , - , View ASPNet. Additive ( , , ), .

, , , , .

Proof-of-concept. , .

مستودع جيثب - https://github.com/HolyMonkey/unity-typed-scenes

إذا كنت مهتمًا ، فسأطلب من فلاديسلاف في المقالة التالية إخبارك بكيفية عمله مع Code Dom في Unity وكيفية العمل مع المعالجة اللاحقة باستخدام مثال ما ناقشناه اليوم.




All Articles