Bagaimana kami menata ulang bekerja dengan adegan di Unity

Unity, sebagai sebuah mesin, memiliki sejumlah kelemahan, yang berkat kemampuan penyesuaian dan alat pembuat kode, dapat diatasi.

Sekarang saya akan memberi tahu Anda tentang bagaimana kami menulis plugin untuk Unity berdasarkan pasca-pemrosesan proyek dan generator kode CodeDom.

Masalah

Di Unity, memuat adegan dilakukan melalui pengenal string. Itu tidak stabil, yang berarti mudah diubah tanpa konsekuensi yang jelas. Misalnya, saat Anda mengganti nama sebuah adegan, semuanya akan terbang, tetapi hanya akan terungkap di bagian paling akhir pada tahap eksekusi.

Masalah muncul dengan cepat dalam adegan yang sering digunakan, tetapi mungkin sulit untuk dideteksi jika berhubungan dengan adegan tambahan kecil atau pemandangan yang jarang digunakan.

Keputusan

Saat menambahkan adegan ke proyek, kelas dengan nama yang sama dibuat dengan metode Muat.

Jika kita menambahkan adegan Menu, kelas Menu akan dibuat di proyek, dan di masa mendatang kita dapat memulai adegan sebagai berikut:

Menu.Load();

Ya, metode statis bukanlah tata letak terbaik. Tapi menurut saya itu desain yang singkat dan nyaman. Pembuatan terjadi secara otomatis, kode sumber kelas ini:

//------------------------------------------------------------------------------
// <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);
        }
    }
}

Dengan cara yang bersahabat, kelas harus statis, karena tidak seharusnya dibuat instance-nya. Ini adalah bug yang akan kami perbaiki. Seperti yang Anda lihat dari fragmen ini, kode kami tidak melekat pada namanya, tetapi pada GUID scene, yang lebih dapat diandalkan. Kelas dasar itu sendiri terlihat seperti ini:

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. , .

Repositori GitHub - https://github.com/HolyMonkey/unity-typed-scenes

Jika Anda tertarik, saya akan meminta Vladislav di artikel berikutnya untuk memberi tahu Anda bagaimana dia bekerja dengan Code Dom di Unity dan bagaimana bekerja dengan pasca-pemrosesan menggunakan contoh dari apa yang kita diskusikan hari ini.




All Articles