如何制作游戏-从商业应用程序和网站开发过渡到游戏

电子游戏是许多程序员渴望的原动力。 我在Commodore 64上长大,并拥有磁带机和自己的3个游戏。 在击败了所有三个人之后,我想要更多……但是小时候,买更多游戏是不可行的。 知道自己买不到游戏,所以我决定尝试制作自己的游戏。 我研究了C64的基本语言,在屏幕上写了文字,发现了惊人的GOTO功能,并做了一些非常糟糕的事情。

虽然我制作的游戏真的不值得玩,但编写自己的代码的经验激发了我的内心。 我意识到,即使是一个孩子,也可以控制计算机,使计算机能够执行我想要的操作……我了解到我可以编写代码。

即使像许多人一样,我最初的编码尝试都是与游戏有关的,但我的第一个实际编程工作与游戏完全无关。 实际上,我的整个职业生涯都花在了商务应用程序,高流量网站,硬件测试工具以及各种其他非游戏软件上。 那时,我遇到了数十位“商业程序员”,他们受到视频游戏的启发而学习了手工艺。 他们中的许多人还长期渴望有一天可以编写自己的游戏。 但是,由于他们是专业的开发商,承担着账单,家庭和责任,所以他们常常难以潜水。 他们中的一些人试图过渡到“游戏开发”中,但是大多数人都难以入门,这是有充分的理由的。

有一种趋势,很多人不得不认为“编程就是编程” ..它们都是一样的,只是使用的库或语法略有不同。 我总是发现这种说法是有缺陷的。 您无需雇用固件程序员来构建高流量的AWS托管网站。 而且我不会雇用数据库工具程序员来为手机编写固件。

尽管所有编程都是松散相关的,并且知道一种形式确实可以帮助您更快地学习另一种形式,但是根据平台,项目和语言的不同,编码方式也存在巨大差异。 游戏开发也是如此。

不过,不要让那让你沮丧。 如果您了解差异并接受差异,则可以快速掌握现有技能并开始制作自己的游戏。 但是关键在于拥抱差异。.如果您像编写WPF应用程序一样尝试编写游戏代码,就会感到苦恼,使生活变得比应有的艰辛,并增加了从未完成项目的风险。

在本系列中,我将介绍一些关键差异。 我将尝试解释如何将您现有的技能转化为游戏开发,并为您提供避免的陷阱。

我想从我看到人们在尝试过渡时犯下的最大错误开始。 与我合作的几乎每个人都首先在这里失败了。

当我说拥抱引擎时,我是说真的拥抱它。 不要像计划中的第一个项目那样开始构建游戏。 取而代之的是,从一开始,就用示例,指南,视频教程或其他任何地方构建一系列非常不同的游戏。 建造可以在一两天内完成的小物件。

想象您正在教一个新的初级程序员您的技术。 如果您是网络开发人员,您会建议他们首先做什么? 建立他们的“ facebook,但更好的克隆”? 还是使用您选择的框架来设置一个简单的示例页面?

请记住,当您切换到新平台和技术时,您就像是初级开发人员一样开始工作。 也许是一个出色的初级开发人员,但仍然初级。

制作这些小型游戏会教给您很多东西。 您会发现,如果您知道自己在做什么,实际上会很容易想到一些您认为很难的事情。

我见过的几乎每个人都在挣扎的另一个领域是基本运动。 我认识的许多开发人员都非常习惯于通过代码在屏幕上移动对象,却从不考虑尝试动画系统。 他们没有花5分钟来制作漂亮的动画,而是花了几个小时来艰苦地编码动作,然后在想要对其进行一点更改时就崩溃了,一切都中断了。 游戏引擎确实可以做很多事情,而动画是他们做得最好的事情之一。

例如,您可能认为构建像《割绳子》这样的绳索游戏需要一些复杂的物理代码,高级数学知识和大量工作。 但是,如果您了解引擎,则无需编写任何物理代码,也几乎不需要数学技能就可以构建整个引擎。

我认识过一些尝试做类似游戏,从头开始编写代码的人,因为他们从未花时间学习HingeJoint2D组件。

在大多数编程环境中,运行着一个隐藏循环。 该循环将消息和事件泵送到您的组件,使您的对象交互变得干净无缝,并为您调用Web控制器方法。 这种抽象对业务和Web应用程序非常有帮助,您不需要自己编写该代码,也不需要这样做。

但是,当您进入游戏开发时,您会注意到该循环是可见的(或非常接近可见的)。 在Unity中,引擎会在场景中活动的每个游戏对象上调用方法,而无需您告知。

这些方法在不同的时间调用,您需要知道如何使用它们。 例如, Awake()方法在对象生命周期的早期被调用,通常用于缓存对其他对象的引用并初始化状态。

Update()方法被称为每一帧,是移动代码和输入处理的常见位置。

但是不要以为您会在Update中进行碰撞检查。实际上,可以追溯到使用引擎,使用OnCollisionEnter,OnCollisionStay,OnTriggerEnter等方法,碰撞会以一种更加有意义的方式发送给您。

等等,碰撞和触发之间有什么区别? 这正是您想早点学习的东西。(触发器不进行物理交互,如弹跳/停止,仅调用代码,而碰撞却像您期望的那样进行)

要了解有关Unity中这些方法的更多信息,请查看此处的执行顺序页面。 它有一个漂亮的图表,向您显示方法及其调用时间:https://docs.unity3d.com/Manual/ExecutionOrder.html

当然,我们都知道游戏的帧速率很重要。 如果跌落得太低,游戏会感觉很糟。 但这也会影响我们的代码的运行方式。

这是因为像Update()这样的方法在每一帧都被调用。 因此,如果您的游戏以10FPS的速度运行,则每秒更新10次。 如果它以300fps的速度运行,那么您每秒就会调用Update 300次。

为什么这么重要? 因为您的代码需要考虑到这一点。 如果每次更新在x轴上将对象移动1个单位,则速度将根据帧速率而变化。 以10fps的速度每秒移动10个单位,以300fps的速度移动很多。

同样,在您可以访问的Time.deltaTime静态浮点中,有一个简单的解决方案。 以此乘以您的移动量将根据您当前的帧速率平滑所有内容……但是您必须知道它的存在才能使用它。

与传统业务编程非常不同的另一件事是项目设置。 以我的经验,我通常有一个解决方案文件,其中引用了一些项目文件,而所有项目文件都引用了代码文件。而且,我在资源文件夹中有几张图片。

在Unity中,设置完全基于文件夹结构,并且代码仅是项目的一小部分。 请记住,这很重要,代码只是项目的一小部分!

您的项目的启动方法是什么? void main()吗? 您不会看到它。 就您的目的而言,它不存在。

相反,您可以从一个场景开始,在该场景中可以进行设置,或者在许多情况下,该场景已经设置好并可以使用了,而几乎不需要代码初始化。

这听起来可能令人不安。 定义应用程序启动方式,依赖项运行位置或初始化所有内容的顺序的代码中没有真理。

它不在代码中,而是在您的场景中。 您可以在场景中设置这些内容。

通常,经验丰富的开发人员会对此进行了解,然后立即使用单个代码文件和用于构建游戏的setup / main方法创建一个“ setup”场景。 不要这样做…。

这正是与引擎作斗争的样子。存在场景是有原因的,这可以使游戏开发变得干净快捷。 在代码中构建所有内容将使其变得更难构建,难以调试,难以扩展以及难以完成……除了具有main()或App_Start()替换的那种温暖舒适的感觉外,没有任何好处。 场景可以为您提供帮助,学习正确使用它们对于成功至关重要。

我过去写过有关Unity中DI的文章。 经过短暂的Web开发后,我对DI的爱重新燃起,我再次尝试用DI构建Unity项目。

依赖注入在大多数环境中都很棒。 如果您在构建网站或商业应用程序时没有使用好的DI容器,则可能会错过……在游戏开发中,DI有点不同。

有一些为Unity进行DI的框架,但是它们并没有获得很大的吸引力..并且有充分的理由..它们也与引擎作斗争。 他们完全按照我刚才说的不做,他们用代码而不是在现场构建游戏。

在某些情况下,游戏中的DI是有意义的,但总的来说我会避免使用它。

您确实需要采用预制和基于组件的开发的概念,而不是使用DI框架。

预制件有点类似于Unity的依赖注入。 无需在代码中配置对象依赖关系,而是在编辑器中进行操作,并创建一个预制结构,以供日后重用。

在这里,我在游戏对象和参考预制件上定义了要生成哪种硬币类型的依存关系,以获取不同的硬币值。

游戏开发的另一个重大区别是引擎通常由基于组件的系统驱动。 在Unity中,这是通过在“游戏对象”中添加“组件”来完成的。 这些组件只是您编写(或与引擎一起提供)的类。 这些类都继承自一个称为MonoBehaviour的通用类,并且正如我之前介绍的那样,这些组件具有内置的方法,这些方法由引擎循环调用。

C#开发人员-值得注意的是,单行为的方法的行为很像被重写的虚拟方法,但是在撰写本文时,它们感觉更像是“神奇的”命名方法,因为它们缺少override关键字。 但是出于您的目的,请想象它们前面有override关键字。

Unity中的每个游戏对象至少包含1个称为转换的组件。 变换处理位置,旋转和缩放。

要在您的游戏中创建一件有用的东西,您将结合各种组件。

例如,如果要创建一个玩家可以抓取的硬币,则需要一个变换,一个球体碰撞器,一个动画师(使其旋转)以及一个自己的脚本来处理被击中和消耗的硬币。

组成可收集硬币的一些组件的示例

在此示例中,您的代码可能很简单, 只需实现OnTriggerEnter()方法并调用一行来销毁硬币……然后再调用另一行即可增加玩家的硬币计数。

基于组件的开发的最大好处是可重用性。 如果将组件开发得较小且通用,则通常可以在游戏对象上对其进行混合和匹配以创建所需的行为。 不要指望立即或在每种情况下都这样做,但是在编写自己的组件时,请始终将其放在首位。

到目前为止,我已经谈论了很多有关开发人员在过渡到游戏开发时遇到的难题。 但是我见过一些技巧,这些技巧在编程的非游戏方面更为常见,可以为您提供良好的入门基础。

扎实的—如果您提倡扎实的校长,那么他们会很有帮助。 我特别关注单一责任主体。 我见过无数经验丰富的游戏开发人员,他们做着令人惊奇的事情,但是却难以理解和使用“单一职责负责人”的好处。 在构建组件时,请记住这一点,使它们保持小巧,可重复使用和可更换。

我发现在网络世界中更流行的另一项技能是对设计模式的充分利用。 重要的是要记住不要使用与引擎对抗的模式,但是当您确实对模式有很好的用途时,具有识别和编码经验的经验将是一个很大的帮助。 一个简单的例子就是知道何时构建一个简单的状态机而不是一个巨大的switch语句……(我已经看到了太多的巨大开关)。 但是,再次重要的是要知道,mecanim引擎中还内置了一个视觉状态机……它主要用于动画制作,但偶尔会扮演其他角色。

当然,您的一般编程经验会有所帮助。 .net框架的知识为Unity带来了巨大的帮助。

我还有很多要讲的..测试,艺术,渲染,资产,音频,场景管理,项目管理等方面的差异。

在后续文章中,我将介绍人们可能在评论中遇到的一些问题和问题。

因此,如果您想知道如何将一些技能转化为游戏开发内容,请询问。


最初于 2017 年7月26日 unity3d.college 发布