作为引擎,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,以及如何使用我们今天讨论的示例进行后期处理。