Wie wir uns die Arbeit mit Szenen in Unity neu vorgestellt haben

Unity als Engine weist eine Reihe von Nachteilen auf, die dank ihrer Anpassungsfunktionen und Tools zur Codegenerierung gelöst werden können.

Jetzt erzähle ich Ihnen, wie wir ein Plugin für Unity geschrieben haben, das auf Nachbearbeitungsprojekten und dem CodeDom-Codegenerator basiert.

Problem

In Unity erfolgt das Laden von Szenen über eine Zeichenfolgenkennung. Es ist nicht stabil, was bedeutet, dass es ohne offensichtliche Konsequenzen leicht austauschbar ist. Wenn Sie beispielsweise eine Szene umbenennen, wird alles fliegen, aber es wird erst ganz am Ende der Ausführungsphase angezeigt.

Das Problem tritt in häufig verwendeten Szenen schnell auf, kann jedoch schwierig zu erkennen sein, wenn es sich um kleine additive Szenen oder Szenen handelt, die selten verwendet werden.

Entscheidung

Beim Hinzufügen einer Szene zu einem Projekt wird mit der Load-Methode eine gleichnamige Klasse generiert.

Wenn wir eine Menüszene hinzufügen, wird die Menüklasse im Projekt generiert, und in Zukunft können wir die Szene wie folgt starten:

Menu.Load();

Ja, die statische Methode ist nicht das beste Layout. Aber es schien mir ein lakonisches und praktisches Design. Die Generierung erfolgt automatisch, der Quellcode dieser Klasse:

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

In gütlicher Weise sollte die Klasse statisch sein, da sie nicht daraus instanziiert werden soll. Dies ist ein Fehler, den wir beheben werden. Wie Sie diesem Fragment entnehmen können, klammern wir uns nicht an den Namen, sondern an die GUID der Szene, die zuverlässiger ist. Die Basisklasse selbst sieht folgendermaßen aus:

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

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

Wenn Sie interessiert sind, werde ich Vladislav im nächsten Artikel bitten, Ihnen zu erklären, wie er mit Code Dom in Unity gearbeitet hat und wie Sie mit der Nachbearbeitung am Beispiel dessen arbeiten, was wir heute besprochen haben.




All Articles