资讯
展览资讯 大型展会 灯光节 大型盛典 赛事 中标捷报 产品快讯 热门话题 艺术节 活动 演出 新闻 数艺报道 俱乐部签约
观点
大咖专访 观点洞察 书籍推荐 吐槽 设计观点 企业访谈 问答 趋势创新 论文 职场方法 薪资报价 数艺专访
幕后
幕后故事 团队访谈 经验分享 解密 评测 数艺访谈
干货
设计方案 策划方案 素材资源 教程 文案资源 PPT下载 入门宝典 作品合集 产品手册 电子书 项目对接
  • 0
  • 0
  • 0

分享

平衡蓝图和C++

2023-07-12

在本文中,我们将探索如何打造符合最佳编码实践的项目,在哪种情况下将代码转为C++更有利。如何在遵循最佳实践的同时使用类,以及如何向设计师和美术师公开变量、函数和事件,以提高开发效率。



1.平衡蓝图和C++:概述


你将学习:
● 了解蓝图和C++的不同优势  
● 遵循最佳编程实践并创建一个的项目
● 了解何时将代码转换为C++更有利
● 编写类并遵循最佳编程规范  
● 向设计师和美术师暴露变量、函数、事件,以便他们在开发中使用。

什么时候适合用C++?什么时候适合用蓝图?两者同时使用时,应该注意些什么?

虚幻引擎的许多系统都基于蓝图和C++开发,所以在语言的选择上,你可能会比较迷茫。在本文中,我们将介绍虚幻引擎中的蓝图和C++,阐述其各自优势,以及如何让它们协同工作,让开发变得更轻松。

本文主要面向有一定行业和游戏开发经验的学习者。虽然不要求你精通虚幻引擎的方方面面,但熟悉引擎有助于你更好地融会贯通。

本文将用到Lyra初学者游戏包中的代码片段。学习本文无需你下载该项目。学完本文后,如果你想进一步探索这个项目,可以访问https://unrealengine.com/marketplace/zh-CN/product/lyra

比较蓝图和C++


学习如何选择用蓝图和C++来构建功能。
如果你刚接触虚幻引擎,可能会倾向于使用你最熟悉的编程语言来创建项目,而且从始至终只用一种语言。但是,如果你知道蓝图和C++各自的最佳使用时机,则能让你的整体开发更加均衡。我们先来简单了解一下虚幻引擎中的C++和蓝图。

蓝图

蓝图是虚幻引擎自创的一种节点化编程语言,它在使用上和C++不同。使用蓝图时,你需要连接各种变量、函数、事件,以此为Actor创建功能(如下图所示)。你还可以借助这些函数和事件,让不同的Actor蓝图相互通信、传输数据。 

蓝图是基于节点的编程语言


蓝图并非完全与C++无关。蓝图在虚拟机层上运行,而虚拟机本质是一种将蓝图解译为C++的独立进程。这意味着,蓝图Actor可能需要占用更多的算力。在后文中,我们会探讨如何降低或消除这种额外开销。但现在,你只需知道蓝图是一种节点化的C++编程方法。

节点化编程有很多好处:可以快速构建代码原型,无需其他IDE,让你专注创意迭代而无需过早关注代码细节。在搭配使用蓝图和C++时,你可以将C++中的函数、事件或变量暴露给蓝图,以便非程序员也能调用C++中的功能。蓝图还能让你快速在项目中编写出更简洁、更轻量的代码,而无需掌握大量编程知识。这是你在选择蓝图和C++时需要了解的重要一点。

蓝图并不局限于创建Actor类——它还能用于创建Gamemode、Game State、Character、Pawn等各种类。蓝图的组件、宏、函数库等功能,还能让你轻松复用各种功能,实现更快、更灵活的设计。总之,蓝图本质上是一种可视化的C++代码,旨在让不熟悉代码的开发者也能编写代码。

Lyra武器中的远程武器蓝图代码。

Lyra初学者游戏包(简称Lyra)中的游戏角色、弹药和其他“轻量级”交互功能都采用蓝图实现。在游戏中,这些功能不像武器或伤害系统需要访问核心代码,因此完全可以用蓝图来设计。下文会说到,C++代码可以暴露给蓝图。许多核心功能都能在蓝图中使用。蓝图不是虚幻引擎的一种封闭式编程语言,而是一种让非程序员编程的方法,团队中的所有人都能通过蓝图扩展C++代码。

C++


使用C++,你可以访问更底层、更广泛,更核心的虚幻功能。你可以修改引擎和编辑器的核心功能,以满足你的项目需求。如果你想修改引擎,改进管线,你需要用到C++!

访问源代码就意味着,你可以编写涉及大量计算的功能,或是快速功能,因为你可以访问更底层的功能。你可以创建游戏核心系统,或是需要大量计算或网络操作的系统。
 
Lyra武器系统中的C++代码

Lyra这类多人FPS游戏有个重要特性,就是需要快速响应玩家输入。这种时候,C++的优势就显而易见了。由于是直接访问虚幻引擎的联网代码和内置玩法系统,性能和带宽开销可以大大降低,创造更好、更流畅的游戏体验。这就是Lyra中采用大量基于C++的网络代码的原因。

虽然游戏开发中,你可以只使用蓝图或C++来构建代码,但你会发现,兼用两者能让游戏功能整体更健壮。我们已经了解了蓝图和C++的各自优势,接下来,我们将深入了解这两种语言对项目结构的影响。


2.蓝图和C++的最佳实践


学习最佳实践,提高项目开发效率。

融合蓝图和C++是一种平衡的艺术。构建项目时,应该充分沿用语言中类、函数、逻辑的内在优势,同时又让团队成员充分发挥特长,创建强大功能。在本小节中,我们将探索项目构建时,需要考虑的决策问题。


在编写代码前,你需要弄清楚哪些功能用C++编写,哪些用蓝图。如何设计游戏架构?为此,你要了解你的团队。团队技能在什么水平?这些问题要尽早了解清楚,以确保你践行最佳实践,避免重复工作。

团队分析


正如你的开发决策受制于游戏内容,决策也会受制于团队构成。根据团队成员的开发技能,某种语言通常会比另一种语言更适合,用起来也更顺手。下面是两种典型的团队结构。
 

以设计师或美术师为主的团队


这种团队拥有较强的设计能力和美术创作能力,但编程能力相对较弱。他们可能更倾向于使用蓝图,而不是C++。如果你们团队也是这种情况,建议你先了解团队常用哪些开发工具,然后用C++编写这些工具,再把它们公开到蓝图中。程序员可以通过这种方式为美术师和设计师提供底层功能,同时确保他们不会访问到不需要的部分。

另外,游戏在结构设计上也应该尽量对美术师和设计师友好,便于他们使用蓝图。集中关注游戏中较为复杂、性能开销较大的方面,但也要确保设计师、美术师能够访问函数、工具来实现他们想要的功能。
 

以程序员为主的团队


如果团队中的程序员比设计师(更确切地说是不会编写C++代码的成员)多,游戏架构又应该如何组织呢?

这种团队可能更倾向于使用C++,而不是蓝图。和前文中的案例一样,你要评估团队的需求。程序员应该把重心放在错综复杂的项目功能上,而不是用C++编写大量游戏逻辑。他们可以添加很多C++代码和功能,然后把变量公开给设计师。

设计师和美术师可以使用蓝图来迭代功能,之后再由程序员转换为C++。
你可能会想到第三种情况:独立开发者。如果是这种情况,擅长什么做什么。如果你懂C++,就用C++。如果你懂蓝图,就用蓝图。

Lyra示例


我们以Lyra中的一个武器数据资产为例,来阐释前面所讲的内容。这个资产主要用来控制一个Lyra武器的各种变量和信息。这个武器的大部分代码都是用C++编写的,目的是为了保证网络性能和游戏性能。武器是用C++编写的,但是在蓝图中公开了很多变量、常用功能和工具类函数,以便设计师使用(下文会讨论),如下所示。
 
Lyra中步枪武器的各种功能和属性。

这么做有利于设计师对武器进行自定义,甚至利用公开的工具和变量创造新的武器。程序员只需要为武器编写一种实用的功能,设计师可以在这个基础上扩展。

其他注意事项和最佳实践


在开发项目之前,还要注意下列问题:

何时用C++编写函数和逻辑

有时候,你可能需要将某些类或函数隔离开来,禁止团队中的其他成员访问。原因有很多,比如不希望非程序员访问这些代码、保护重要代码等等。但是在哪些情况下一定要这么做?在哪些情况下应该编写只能由程序员修改的C++代码?有些游戏机制更适合用蓝图来编写,特别是在考虑到整体复杂性和运算量时。蓝图更适合编写一些临时或“转瞬即逝”的游戏功能。相反,持续在后台运行的永久功能最好用C++来编写。如果你的游戏包含很多小机制,这些机制只会短暂出现,那么请多用蓝图来实现它们。如果你的游戏包含需要进行大量计算和持续计算的功能和机制,则用C++来实现。

避免构建高开销的蓝图

正如上文提到的,蓝图的性能开销比C++大,因为它们在虚拟机上运行。如果一个蓝图包含大量代码,可能会对项目的性能造成很大压力。如果这类大开销蓝图频繁用到,建议用C++替代,或者将一部分功能转移到C++中,以加快速度。

谨慎使用枚举器和结构体

虽然蓝图支持枚举器(Enumerator)和结构体(Struct),但它们中的有一些如果是蓝图的一部分,则不能在C++中使用。不是所有枚举器和结构体都有这个限制,如果要在C++中使用,就要确保你想使用的枚举器和结构体在C++中可访问。
 

小结


综上所述,在发挥蓝图和C++的最佳功效时,往往伴随着在两者之间找到平衡,而这种平衡会受到多种因素影响。游戏解构和团队结构都会影响你最终选择的语言类型。如果你的游戏包含很多持续运行的机制,或者你的团队更擅长编程,就应该考虑使用C++而不是蓝图。说到底,你应该充分考虑团队和游戏本身的侧重点,以此决定哪些内容用哪些工具开发。


3.使用蓝图和C++优化项目


学会判断什么时候将蓝图转换为C++,以提高项目性能。


前面我们探讨了平衡C++和蓝图的艺术,但是在某些情况下,更适合只用其中一种。在本节中,我们将通过不同的示例来了解,在哪些情况下一种语言比另一种语言更合适。

C++和高开销内容


正如之前所说,C++更适合用来构建游戏中长期需要的函数和工具。但我们没有具体解释原因。蓝图也可以构建同样的持续性功能,但可能会产生额外的性能开销,因为它们要在虚拟机上运行。如果游戏中长期大量存在这种蓝图,你可能要考虑将其中一部分转为C++。有很多方法,比如使用蓝图原生化功能(Blueprint Nativization)。
 
蓝图代码通过虚拟机与C++通信。

通过C++,你可以直接访问虚幻引擎的函数和工具类,这意味着你可以更灵活地控制对象,以及决定何时何地进行处理。直接访问是关键。除此之外,你可以用C++类来搭建蓝图的基类,然后用蓝图扩展这些基类,以满足性能目标。Lyra初学者游戏包中就是这么做的,先用C++创建基类,再用蓝图扩展它们的功能。

在Lyra中,很多功能是用C++编写的,因为对联网、持续活跃的功能来说,C++的性能表现更好。就像之前说的,对于需要快速响应枪械命中的游戏,最好直接访问引擎代码,以确保减少延迟,快速做出响应。

此外,涉及大量计算的功能,或者需要持久保存数据的功能(例如在会话间保存和加载数据),最好用C++。虚幻引擎提供了很多优化工具,这些现成工具能帮助你识别哪些功能需要大量算力,进而使用C++。
 
内容浏览器中的Lyra步枪蓝图。

何时使用蓝图?


现在你可能会想:为了获得更好的性能,是不是所有内容都应该用C++来编写?但实际并非如此!这还取决于游戏架构以及蓝图在该架构中的用法。Lyra的做法是用C++编写基类和许多底层功能,然后向蓝图公开一部分C++功能。以C++类为基类,创建蓝图基类,并把C++功能继承到蓝图中。这样,设计师可以创建蓝图的子类,根据需要进行扩展,创建他们想要的内容,但是背后仍然有C++功能作为支持,以确保优化性能。

你可以参考Lyra初学者游戏包中的武器和武器生成类,全都来自基于C++类创建的蓝图类,并且有相应的蓝图子类。

在这种方法中,派生类中适合添加轻量级功能;这些功能通常不会对性能产生很大影响。如果某个功能会产生巨大性能开销,它应该转成C++,然后公开给蓝图,供设计师使用。轻量级代码(例如在蓝图中调用C++函数、简单的定时器或设置整数)都无需用到C++。这些功能用蓝图实现更合适,因为它们通常由设计师和美术师掌控,而且是轻量级功能。
 
玩家生成器的蓝图。

我们已经讨论过为什么蓝图的性能略逊于同等的C++类,原因是蓝图在虚拟机上运行。降低这种开销的一个简单方法是禁用蓝图。禁用蓝图的Tick事件,或者降低Tick频率,比如用Timeline或其他事件函数来控制蓝图的生命周期,从而减少性能开销。

最后,如果蓝图占用了大量计算带宽,可以考虑启用蓝图原生化。这个功能可以将蓝图转换为原生C++代码,小幅提升性能。请参阅虚幻引擎相关文档,了解更多内容。

小结


尽管我们会尽量兼用C++和蓝图,但有时候,只适合使用其中一种。接下来,我们将探讨项目核心类应该用哪种语言来构建,并解释原因。


4.根据类来选择使用蓝图或C++


根据对象的类类型来选择蓝图还是C++。

Actor该用什么语言编写?


游戏是由一系列常见的核心Actor和类组成的,比如游戏模式、游戏状态(或游戏实例)、Pawn/角色。这些都是游戏运行所必需的,设置这些Actor和类是每个团队都必须要做的工作。

你可能会想,某些Actor是否就一定适合只用某种固定类型的语言编写。对于核心Actor来说,答案是“对”,一种语言可能比另一种语言更有利。但归根到底,最终取决于团队架构和团队具备的技能。如果团队中程序员比较少,可能会倾向于使用蓝图。我们将以Lyra为例,研究FPS游戏中的核心Actor什么时候适合用蓝图,什么时候用C++。

案例分析


Game State - Lyra的游戏状态使用了C++,因为它负责处理游戏的状态/阶段逻辑。就像之前说的,需要进行大量计算,或涉及持久计算的游戏功能,最好使用C++实现。考虑到潜在的网络处理逻辑(包括客户端和服务器),使用蓝图会影响性能。
 
游戏状态的C++代码。

Pawn/Character  - 观察玩家Pawn,你会发现游戏中的玩家是一个蓝图类的子类,而这个蓝图类继承自一个C++类。它是一个多层继承结构,但是遵循我们之前所讲的:使用C++编写底层功能,暴露给蓝图,再从蓝图派生子蓝图类,再用蓝图扩展功能。这样就可以充分利用两种语言各自的优势:C++的高效,蓝图的迭代和扩展。
 
Lyra玩家Pawn的蓝图代码。

Game Mode - 和上文类似,Lyra的游戏模式也用C++编写。在服务器端,代码需要有足够强大健壮,才能跟上服务器的速度。如果要新建GameMode,你可以创建子类,这样就能保持性能,同时自定义你的体验。
 
Lyra的游戏模式设置。

图中是Lyra的游戏模式设置。当然,如果你的游戏状态无需在服务器端复制,或者不需要处理游戏逻辑,你也可以用蓝图实现。虚幻引擎默认提供了Pawn和Character模板类,其中包含完整的蓝图功能,方便你在其基础上扩展。前面我们反复提到,具体选择应该取决于你的团队架构和团队掌握的技能。C++有C++的好处,但如果你不会C++,也可以用蓝图。Epic Games的VR游戏《Robo-Recall》(2017)就是主要用蓝图开发的!

小节


不同资产适合用不同语言实现,这不仅有利于项目开发,还有利于减轻你和团队的工作负担。不过,这只是改善团队合作的一个方面。接下来,我们将探讨如何进一步搭配蓝图和C++来助力团队协作。


5.将C++功能暴露给蓝图以便协作


将C++功能暴露给蓝图,方便团队合作。

团队中未必所有人都精通编程。即使人人都会,一些轻量级功能也不应该用C++代码实现。将项目的部分功能暴露给美术师、设计师以及其他团队成员,有助于加快开发迭代,方便团队发挥创意。在本节中,我们将进一步讨论这个话题,并将展示实际项目中的一些方法。

“公开”还是“不公开”


C++中的函数、变量、事件和数据都可以暴露给蓝图,供整个团队访问。将C++暴露给蓝图,就可以在蓝图中调用和/或使用C++函数、变量、事件和数据。这意味着,如果程序员编写了一个C++事件,比如玩家穿过门时会触发一个事件,那么我们就可以在蓝图中暴露并响应这个事件。美术师和设计师可以在蓝图中扩展该事件,然后创建他们想要的功能。
 
在C++中将代码暴露给蓝图。

这是蓝图和C++最强大的特性之一,但在用前有几点要考虑清楚。首先,你的游戏架构要支持这种类型的功能暴露。如果当前使用的C++类包含重要信息,禁止公开,团队中的其他人就无法访问这些数据。

此外,游戏架构不仅要支持程序员,也要支持美术师和设计师的工作流程。如果美术师需要用变量来控制光源,那么就应该暴露这些变量。他们不需要访问这些变量的底层计算逻辑,只需要控制变量本身。这能为美术师和设计师带来更大的自由度和灵活性。在构建项目底层的时候,要认真考虑团队的需求,从长远角度来说也大有裨益。

你可以在Lyra武器中看到公开的变量。武器的主要功能——什么时候发射子弹、子弹击中目标后会发生什么等等——都用C++编写,并且是“隐藏”的。这样可以确保代码不会被非程序员意外修改,从而破坏开发。这些代码用C++编写的,然后再公开到蓝图中,以确保联网体验的流畅。

如果在虚幻引擎编辑器中打开Lyra的武器蓝图,你会发现设计师可以调整大量公开数据,例如弹药数量、弹匣大小、重生时间等等。设计师可以自行调整平衡性,设计弹夹容量时不需要程序员协助。这不仅节省了设计师的时间,也节省了程序员的时间。
 
Lyra步枪实例中的属性。

在确定是否公开这个问题上,最简单的方法是问自己和团队:“设计师会不会调用这个函数?”或者“设计师需要调用哪些事件?”尽早、经常地考虑这些问题有利于C++底层构建,改善团队的工作流程。

对编程产生的益处


采用这种工作方式有一个额外好处。只公开特定的事件和函数,可以让设计师和美术师与程序员的工作解耦。核心代码可以“隐藏”起来,程序员可以在不频繁干扰其他团队成员的情况下工作。这可以大幅改善工作流程,尽可能避免干扰其他团队成员的工作。

小节


与设计师合作,了解他们的需求,编写出他们需要的复杂底层代码。然后,只公开他们需要的功能。打破只有程序员可以修改变量和函数的思维,这能帮助你走向成功,开发出更好的项目。

向美术师和设计师公开变量、函数、事件等,让他们能够根据自己的需求修改,不需要寻求程序员的帮助。这可以为他们带来更大的创作自由,加快开发速度。接下来,我们将回顾本文的所有内容。


6.平衡蓝图和C++:总结


我们谈到了项目中C++和蓝图的平衡的艺术。不要过度使用一种语言,因为单靠一种语言不足以应对所有情况。我们还介绍了用特定语言来创建特定的类能让你事半功倍,谈到了如何正确地构建和使用这些类和资产。我们还介绍了平衡C++和蓝图的好处,结合C++与蓝图可以为团队赋能,使开发流程更加顺利。

学完本文后,你可以试着用你掌握的C++和蓝图知识构建虚幻引擎项目了。

想学习更多技能吗?我们在Epic开发者社区为大家提供了很多学习资源,这些资源可以帮助大家继续学习!



阅读原文

* 文章为作者独立观点,不代表数艺网立场转载须知

本内容由数艺网主动采集收录,信息来源为 “虚幻引擎” 公开网络发布内容。第三方如需转载本内容,必须完整标注原作者信息及 “来源:数艺网”,严禁擅自篡改、删减或未标注来源转载。 并附上本页链接: 若您的内容不希望被数艺网收录,或认为此举侵犯了您的合法权益,敬请通过微信 ID:d-arts-cn 联系数艺网。我们将致以诚挚歉意,并第一时间为您办理下架或删除处理。

数字媒体艺术 新媒体艺术 科技艺术

14381 举报
  0
登录| 注册 后参与评论