【问题标题】:Discussion about separation of game logic vs. Unity scipting关于游戏逻辑与 Unity 脚本分离的讨论
【发布时间】:2018-02-20 01:50:46
【问题描述】:

如果这个问题的论坛有误,请引导我到正确的论坛。

我正在学习 Unity,我一直在努力遵循整体的关注点分离架构模式,例如 MVC,并使我的游戏单元可测试。我一直在尝试遵循 MVC 模式,其中我的 Unity 对象是我的视图,我的游戏逻辑在我的模型类中。

例如,对于我的玩家角色,我将 Unity 对象视为我的“视图”,并在其上附加了 PlayerCharacterScriptPlayerMovementScript。它们都是Mono-Behaviour 派生类,实现特定于 Unity 的行为,例如确定用户点击移动的位置以及在用户受到伤害时播放动画。

然后我有一个Player 类(我的“模型”),它具有游戏逻辑,例如当玩家生命值低于 0 时导致其死亡。当玩家发生需要视觉响应的事情时,Player 类会调用 Action,例如 OnDeathPlayerCharacterScript 正在监听它。然后PlayerCharacterScript 播放死亡动画作为回应。

理论上这很有效,模型类很容易进行单元测试。我的问题是,在实践中,将模型和视图 (MonoBehaviours) 添加到场景中并来回发送消息变得非常烦人。例如,如果我在 Unity 编辑器中将Goblin 预制件拖到我的场景中,那么当游戏开始时,那个地精的MonoBehaviour 需要创建其对应的Goblin 模型,将该模型添加到“场景管理器”类,并将Goblin 对象设置为MonoBehaviour 的模型。

但是,在“场景管理器”类的游戏逻辑中,我想在场景中创建一个地精以响应某些动作。由于这是游戏逻辑,它将成为模型类的一部分(不是MonoBehaviour)。在这种情况下,我首先创建模型,然后我必须创建带有关联MonoBehaviours 的预制件,将其添加到场景中,并使用MonoBehaviour 注册该模型。

现在我遇到了一些情况,有时MonoBehaviour 创建模型,有时模型创建其预制件/MonoBehaviors。我还必须记住,每次创建任何类型的新游戏对象预制件时,我都必须在其中放置一些样板代码,以便 Unity 对象创建它的模型。另一个问题是,如果我的模型需要调用 AwakeStart 方法,我的模型永远无法创建派生自 MonoBehaviour 的新对象,因为这在单元测试期间不起作用。

追求这种模型/视图架构似乎变得比它的价值要麻烦得多,而且将包括游戏逻辑在内的所有内容都放在MonoBehaviours 中会更容易。

我四处寻找有关此主题的建议,发现的只是一些关于如何使游戏逻辑单元可测试的帖子,但没有一个解决代码变得混乱的问题如果平台在设计时没有考虑到显示逻辑和游戏逻辑的分离,而 Unity 似乎并非如此。

我很想听听任何有经验的 Unity 开发人员的意见,我是否应该继续将游戏逻辑与 Unity 逻辑分离,或者最终是否值得。

【问题讨论】:

    标签: unity3d


    【解决方案1】:

    第一个 MonoBehaviour 是你的逻辑而不是你的结构的地方

    对于结构使用 ScriptableObject,可编写脚本的对象非常方便,可以将其视为游戏对象(单一行为),无需转换,无需启动、更新、唤醒等。只是数据模型和......就像您可以添加的任何类函数,但 Unity 不会自动调用。

    举例

    [CreateAssetMenu(menuName = "Custom Objects/SimpleObject")]
    public class SimpleObject : ScriptableObject
    {
        public float myData;
        public GameObject someReference;
        public Vector3 someMoreData;
    }
    

    现在您可以将游戏“模型”与游戏逻辑“控制器”分开定义? ... 一款游戏不会完全符合 MVC 或 MVVC 范式,但这并不意味着您不能通过从中获得改进来改进游戏的结构。

    有一个关于像这样使用 ScriptableObjects 的精彩演讲,它确实强调了在推广可测试的模块化游戏结构中的用途。 https://www.youtube.com/watch?v=raQ3iHhE_Kk

    我们(Heathen Engineering)也开发了一个基于这些概念的框架......但我不会在这里自我宣传,如果您想了解更多信息,请给我留言。

    【讨论】:

    • 感谢您的链接。那很有趣。一个问题:对于一个老派风格的 RPG,当玩家移动到一个新区域时,你经常在场景之间切换,你如何处理设计每个场景并在场景之间保持数据,因为你不使用单例?由于可能有数百个较小的场景(主要城镇 A、房屋 A1、房屋 A2、主要城镇 B、房屋 B1 等),您如何处理构建场景?如果我决定创建一个新的 ScriptableObject,我不想经历 100 个场景并添加它。
    • 我建议写一个单独的问题,无法在 1 条评论中回答。负载添加剂的注意事项,例如一次加载多个场景并将您的游戏分解为更小的部分。至于数据持久化,这是 Scriptable Objects 的一大优点……它们不会存储在它们存在于资产数据库中的场景中,因此它们会在场景加载之间自然地持久化。
    猜你喜欢
    • 2016-02-05
    • 2017-10-03
    • 2011-11-03
    • 2017-08-15
    • 2017-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多