混合蓝图和 C++


? 没有两难选择。如果可能,您的项目应该同时使用这两种方法。蓝图可视化脚本并未被设计为完全取代 C++,尽管它是一种令人惊叹的脚本形式。它允许非程序员角色的人编写游戏逻辑脚本。

? 是的,可以仅使用蓝图来完成和发布游戏。

  • 如果您是业余爱好者、独立开发者或只是学习如何创建游戏,那么仅蓝图项目可能是开发游戏的绝佳方式。在 gamedev 中有很多东西要学,所以一开始就跳过传统编程语言的学习将节省大量时间。并不是每个人的头脑都能够轻松地消化基于文本的编程。视觉脚本更适合艺术家、关卡设计师或作家的大脑。

  • 但是,一个团队通常会包括一名程序员。或者很多。

    如果您的团队中有程序员或任何部分时间花在 C++ 编程上的人,您只需将这两种解决方案混合使用即可。可视化脚本旨在补充基于文本的编程/脚本,将程序员从内容创建者可以轻松完成的脚本中解放出来。

Epic 的本指南很好地介绍了如何在项目中平衡 C++ 和蓝图。简而言之,建议将 C++ 用于通用核心系统,将蓝图用于扩展这些系统并需要快速迭代以进行平衡和测试的特定游戏机制。例如,团队中的程序员会使用 C++ 为游戏设计一个通用的能力系统,然后团队的游戏设计师会使用蓝图在蓝图中制作一个火球能力。

为什么项目还需要经典的编程和程序员?

  • 脚本语言的效率通常低于 C++ 代码:执行速度较慢,使用更多内存。

    • 不过,大多数时候蓝图脚本对性能的影响并不明显。蓝图中确实存在一些常见的性能陷阱,您无法通过应用[基本蓝图实践](https://unrealcommunity.wiki/Fundamental Blueprint Practices)来避免这些陷阱。
    • 更大的问题是由专门使用可视化脚本的人创建的混乱蓝图引起的。他们根本没有机会学习编程概念和实践。这些可能会严重影响迭代时间和整个代码库的质量。是的,从节点组装代码可以很快,但混乱的代码会导致技术债务——很难使用它或围绕这个混乱的代码构建其他功能。
    • 蓝图人显然可以学习正确的编程,但是蓝图非常易于使用,所以很多人喜欢“以任何方式”编写脚本。“任何方式”通常是一种可怕的方式。糟糕的代码仅仅意味着很难理解,即使对于它的作者来说也是如此。在杂乱的代码中更改小东西需要更多时间,而且容易出错。如果代码过于复杂且设计不良,则很容易产生错误。
    • 学习任何常规编程语言都有助于学习如何有效地使用蓝图。即使在 Unity 中学习 C# 也会对您有很大帮助,因为它会向您介绍编程概念。
  • 基于节点的脚本只提供了底层编程语言中可能的有限子集。蓝图提供了大量虚幻 C++,可以实现原型和大量带有节点的游戏脚本。尽管如此,它只是被称为 C++ 的通用多范式语言的一部分。

    • 只有暴露于虚幻属性系统(反射)的事物才能暴露于蓝图。这意味着我们只能在蓝图中使用 Epic 在引擎中处理的 C++ 的这些数据类型和特性。您可能会认为您没有缺少蓝图中的任何内容,只是因为您不了解 C++ 功能。
    • 实际上,并非所有用 C++ 实现的特性都可以暴露给蓝图,即[编程子系统](https://unrealcommunity.wiki/Programming Subsystems)就是一个简单的例子。
    • 蓝图仅支持面向对象编程。每个蓝图都代表某种“对象”,继承于 UObject 类。检查[基本对象类](https://unrealcommunity.wiki/Basic Object Classes)以查看“参与者”和“组件”在其中的位置。这样的设置对于创建虚拟世界来说是非常自然和直观的(现实世界中的一切都是一种对象,对吧?),但这并不是唯一的编程方式。
    • Slate - 用于创建所有编辑器 UI 的 UI 框架 - 利用另一种称为“声明性语法”的编程范式。这里没有 UObject,Slate 不能存在于蓝图中。编辑器 UI 只能在 C++ 和 Slate 中创建和自定义。
    • 游戏内 UI 是使用 UMG(请参阅UMG UI Designer 快速入门指南)创建的,它是通过称为 UWidget 的特殊类向 UObject 公开的 Slate。使用 UMG 创建的每个游戏内元素都是一个“小部件”,一种无法放置在世界本身中的对象。
  • 连基本的 C++ 都不懂的人是无法阅读和调试引擎代码的。这意味着他们永远不会了解引擎中发生了什么,以及在蓝图中调用给定函数时实际发生了什么。他们只能猜测游戏是如何运作的,因此他们需要程序员的支持。引擎文档和互联网永远不会回答所有问题。

  • 因此,没有程序员的团队将无法修改引擎代码——这在使用 Unreal 时很常见。它完全是可选的,但非常有用。

    • 引擎代码中的一个小改动可能允许实现一个游戏特定的功能,否则这是不可能的。团队将不得不忘记该功能或以肮脏的方式实现它(未修改引擎代码的解决方法)。
    • 您可以快速修复引擎中的错误和崩溃。通常是更改几行代码的问题。这在游戏即将发布时可能非常重要——您只需要在当前引擎版本上发布游戏,但有一些关键的引擎错误需要修复。
    • 有时您可以轻松地集成“来自未来的更改”,这是引擎开发人员分支中相对较小的引擎(对某些系统的错误修复或改进)。
  • 上述观点也适用于从市场下载的插件代码。许多插件的代码并不完美,有时需要调试和修改。

蓝图的优势

  • 快速原型制作。使用编辑器内的工具(包括蓝图)对机制、事件、任何类型的疯狂想法进行原型制作非常容易。这可以由非程序员完成。与其浪费时间准备新想法的文档并试图向程序员解释它们,您可以简单地实现自己的想法。通常,开始组装蓝图就足以注意到给定的想法行不通。您需要在实施时放弃或重新设计它。您不会等待程序员,也不会浪费程序员的时间来实现在早期通常无法正确解释的粗略概念。
  • 对资产进行操作。蓝图是代码(每个蓝图都是基于 UObject 的类)和数据的结合。在蓝图代码中连接任何资产是很自然和容易的,即材料、纹理、音频,你说的。在基于文本的代码中,完全相同的事情可能非常麻烦。通常,程序员必须创建一个新变量来获取资产引用、硬编码资产的路径(因此如果资产名称发生更改,则需要手动更新代码......),或者创建一个资产作为其他资产的列表。 ..
  • 小脚本。单个演员的任何脚本,即门的行为方式或玩家与胸部交互时会发生什么。在重度指导的游戏中有成百上千个这样的脚本。每个独特的对象、游戏的每一分钟或地图上的每个地方都有一些特定的脚本来丰富体验。在 C++ 中隐藏这些东西是没有意义的,而且会适得其反。尽管建议在代码中定义一个通用类的基础(即 NPC、spawner、门、带战利品的箱子)——确保应该用 C++ 编写的系统之间的轻松互操作性。
  • 脚本动画和 UI。开发人员可以通过动画蓝图编写动画状态。并使用 UMG 蓝图实现 UI。甚至程序动画系统——Control Rig——也部分基于蓝图。
  • 简单的编辑器脚本。可以通过编辑器蓝图编写一些编辑器操作的脚本。虽然最近我们也可以使用Python 进行编辑器脚本,这是艺术/VFX 工具中常用的语言。

C++的优点

  • 复杂的数学和算法。在可视化脚本中组装复杂的逻辑既慢又烦人。这可能需要大量点击蓝图,节点不适合窗口(在大型节点网络上很难操作)并且运行时性能会更差。虽然用 C++ 编写相同的东西会非常快,只需添加几行文本。
  • 访问所有引擎和编程功能。我们不使用原始 C++ 编写游戏代码,我们主要使用所谓的“Unreal C++”。Epic 使用自己的核心 C++ 库扩展了 C++,专为开发视频游戏而设计。请阅读另一篇描述[Unreal C++](https://unrealcommunity.wiki/Unreal C++)的文章。
  • 大部分引擎都是用 Unreal C++ 编写的。如果您知道为您的游戏编写 C++,那么您已经了解了很多引擎代码。
  • 编写 UI 自定义和自定义编辑器的能力。UE4中有几十个编辑器专门针对特定的游戏系统。这就是使该引擎成为如此强大的创建工具集的原因。没有什么能阻止您创建自己的项目特定编辑器,这对您的团队来说可能是一次令人难以置信的升级。
  • 蓝图是二元资产。您不能简单地合并蓝图。可以看到蓝图版本的差异,但只能以视觉形式(并排显示两个图表)。重构复杂的蓝图需要更多时间。蓝图对于代码的关键部分和游戏的核心并不是一个很好的解决方案。
  • 系统。由于上述所有这些原因,C++ 成为您应该实现游戏系统的唯一地方。它为您提供了快速的迭代时间、最佳性能以及对非程序员用户可用内容的完美控制。
  • 高效实施网络游戏。蓝图可以处理许多多人游戏功能:复制、仅执行代码服务器或客户端等等。游戏能力系统允许设计师利用高级多人游戏 API,这些 API 不能简单地暴露于蓝图。然而……多人游戏为游戏开发增加了一个整体。必须考虑每个对象、功能和数据。它只存在于服务器上吗?或者这个对象在服务器上更新,但必须将更改复制到所有客户端?或者也许是拥有客户?这些东西