c# - 在Unity3D中管理复杂的预制层级

标签 c# user-interface unity3d unity3d-gui unity3d-editor

我在几个地方问了这个问题,但还没有完全弄清楚,所以也许一些聪明的人会想到如何解决这个问题。

在项目中维护预制件的深层嵌套层次的最佳方法是什么?假设我们有几个由较小的通用组件组成的GUI屏幕。为了简单起见,我们将前者称为“视图”,将后者称为“组件”。视图处理语义(例如库存视图,商店视图);组件是可配置的,但没有任何附加的业务逻辑(例如,按钮仅关心其OnTap回调/事件处理程序)。

视图和组件都可以嵌套。

GUI视图需要在多个场景之间重用。

Unity中这种方法的主要问题是,任何嵌套的层次结构一旦变成预制件,便会失去对其子预制件的引用,例如以下示例(完全组成,但仍然有效):

- storeView - UIViewHeader - UIHeaderLabel<Text> - UIList - UIListItem - UIThumbnail - UITitleLabel<Text> - UISubTitleLabel<Text> - UIPrimaryButton<Button> - ...

我想将所有这些较小的UI *组件保留在单独的预制件中,但还要保留storeView预制件,以便可以轻松地将其添加到不同的场景中。不幸的是,当我们创建storeView预制件时,所有UI *预制件引用都将丢失。
鉴于此,我们可以尝试一种不同的方法,在该方法中,不使用带有内容的storeView预制件,而是将其保留为空,然后选择以下几个选项之一:


在运行时将行为附加到storeView并加载子预制件


缺点:使设计人员的工作流程更加复杂,将复杂性置于脚本中,从开发人员的角度来看,也可能更容易出错
优点:可以更轻松地在场景之间重用storeView,可以对组件预制件进行样式设置,全局修改

将storeView保留为空的预制件,并在需要它的每个场景中重新组装它


缺点:组件需要手动连接,仍然很容易意外地保存整个storeView并丢失预制参考
优点:保证维护组件预制引用,允许视图之间的细微差别(实际上是个问题,因为这些应该属于配置层)

将整个storeView保存为预制件


缺点:扩展性极强,使得迭代新功能或小的UX更改更加耗时(其他质量检查,验收测试等)。
优点:这是一个快速且肮脏的解决方案,适用于小型项目

使用Prefab Evolution或类似产品


缺点:我认为该包装将被Nested Prefabs淘汰,这在路线图上是什么?要求取决于第三方代码,可能不够灵活(这里有什么意见吗?
优点:从我所看到的许多(混合)评论中,有些评论是非常正面的。但是,项目越复杂,这些评论就越不积极。

编写一堆自定义编辑器脚本:


缺点:也很耗时-似乎应该由平台提供,即使它主要处理游戏
优点:可以完全控制行为,开发人员可以在设计人员的反馈下加以改进。有人可能会争辩说,由于功能需求而受到约束,必须具有实施,测试和对设计人员友好的工具,这听起来像是一种好的设计实践(导致更少的技术负担,更易于维护)



这是我针对此的个人的,理想的,不切实际的解决方案*:

使用组件化的体系结构,默认情况下,子预制组件引用存储在复杂的预制组件中。在内部将它们视为UIView和移动(Cocoa)上的子视图,或者是React或更好的功能组件中的组件类-React / Cycle / Elm /与FRP相配的任何东西(是的,我知道这些方法在很多方面都存在差异,但关键是可组合性,可以通过功能组合物,装饰物等实现)。


缺点:我认为我的困难来自我对Unity的缺乏经验,并且有一个更明显的,也许是惯用的解决方案(我很乐意要求:))
优点:使新功能的测试和迭代更容易,使预制件更强大,同时又不损失其任何优势(如果我错了,请纠正我,我仍然熟悉Unity)
请不要以为我期望Unity提供所有这些功能,但这是可能的方向之一,即使其中1%是正确的。


明确地说,对于Unity来说并不是什么麻烦,作为一个以前使用移动(本机)和Web的开发人员,我发现它给我留下了深刻的印象,它解决了我的许多问题,以及其中一些解决方案多么简单的荒谬。

最佳答案

我可能会在单独的场景中维护合成视图。只需考虑这些场景,因为它们是预制的,只包含给定类的单个原型对象。

SceneManager.LoadSceneLoadSceneMode.Additive一起使用,您甚至可以创建一些静态工厂方法,例如:

public class UIStoreView
{
    public static UIStoreView Instance()
    {
        SceneManager.LoadScene("UIStoreView", LoadSceneMode.Additive);
        return GameObject.Find("UIStoreView");
    }
}


通过一些命名对流,您可以实现与storeView = UIStoreView.Instance();一样简单的功能。

这不是通用的/可扩展的东西,但是至少您要轻巧/可维护,直到它们推出嵌套的预制件(如他们所说的timeline uncertain)。

关于c# - 在Unity3D中管理复杂的预制层级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40979856/

相关文章:

c# - 如何从单声道的 C++ 中获取某个类中所有方法的列表?

c# - 启用 URL 重新路由后 Ajax 停止工作

c# - 在 C# 中使用 C++ 函数

c# - 在 WPF 中创建自定义关闭按钮

c# - 通过脚本找对撞机

c# - 使用 2 个其他数组对数组进行排序

mysql - 如何处理从游戏中不断更新的数据库

c# - java构造函数上的c sharp等价物

c# - 使 WPF 按钮看起来不那么扁平

java - 如何让 JFrame 显示我的 GUI?