エンジンとしてのUnityには多くの欠点があり、カスタマイズ機能とコード生成ツールのおかげで解決できます。
次に、プロジェクトの後処理とCodeDomコードジェネレーターに基づいてUnityのプラグインを作成した方法について説明します。
問題
Unityでは、シーンのロードは文字列識別子を介して行われます。安定していません。つまり、明らかな結果なしに簡単に変更できます。たとえば、シーンの名前を変更すると、すべてが飛んでいきますが、実行段階の最後でのみ表示されます。
この問題は、頻繁に使用されるシーンですぐに発生しますが、小さな追加シーンやほとんど使用されないシーンでは検出が難しい場合があります。
決定
プロジェクトにシーンを追加すると、Loadメソッドを使用して同じ名前のクラスが生成されます。
Menuシーンを追加すると、プロジェクトにMenuクラスが生成され、将来、次のようにシーンを開始できます。
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. , .
GitHubリポジトリ-https://github.com/HolyMonkey/unity-typed-scenes
興味があれば、次の記事でVladislavに、UnityでCode Domをどのように操作したか、そして今日説明した例を使用して後処理を操作する方法を説明するように依頼します。