本文主要来自<>哈里森.费隆 著,仅用为做笔记。
定义变量
首先,什么是变量?目前存在如下几种观点:
- 从概念上讲,变量是编程的最基本单位,就好比原子,一切都基于变量,没有变量,程序就不可能存在。
- 从技术角度看,变量是用于存储指定值的一小部分计算机内存。变量会跟踪信息的存储位置(称为内存地址)以及值与类型(例如:数字,单词).
- 实际上,变量相当于容器。可以随意创建新变量,然后赋值,移动位置,并在需要的地方引用。即便空的变量也是有用的。
举个粒子--邮箱,如图所示,邮箱是可以装信件,账单,照片等任何东西的。关键是在于邮箱中的东西是可变的。
变量可以理解为是我们程序可以操作的内存区域的名称,在 C# 中每个变量都有自己特定的类型,这个类型确定了变量所占内存的大小、布局、取值范围以及可以对该变量执行的操作。
可以将变量当作一种通过符号(变量名)表示某个内存区域的方法,变量的值可以更改,并且可以多次重复使用。C# 中的基本变量类型可以归纳为以下几种:
类型 | 示例 |
整型 | sbyte、byte、short、ushort、int、uint、long、ulong、char |
浮点型 | float、double |
十进制类型 | decimal |
布尔型 | true、false |
空类型 | 可为空值的数据类型 |
变量的名称很重要
如果你去打开邮箱,你的第一反应可能是问:"打开哪一个?",如果告诉你打开史密斯家的邮箱,棕色的邮箱,你就知道该怎么做了。
类似地,在创建变量时,必须为它们指定唯一的名称,以便以后引用。我们会在后面讨论有关格式化和命名变量的更多细节。
将变量作为占位符
实际上,创建和命名变量相当于给需要存储的值创建占位符,以如下简单的数学算式为例:
2+9=11
如果想把数字9改成变量的话,考虑以下代码:
myVariable=9
现在,我们可以在任何地方使用myVariable变量代替数字9.
2+myVariable=11
尽管还不是真正的C#代码,但以上示例演示了变量的功能以及如何将它们作为占位符进行引用。
1.实践---创建变量
介绍的理论知识已经足够了,现在在LearningCurve脚本中创建变量,不必担心语法:
首先双击Unity项目中的LearningCurve脚本,打开VS编辑器,参照上面的代码。在Unity中运行脚本时,需要把脚本附加到场景中的游戏对象(在UNITY中称为GameObject)上。此时,项目中只有相机和方向灯。因此,我们选择把LearningCurve脚本附近到相机上,这样比较简单。
(1)把LearningCurve脚本拖到Main Camera上
(2)选择Main Camera,它将出现在Inspector面板中,检查LearningCurve脚本是否已正确附加到Main Camera上
(3)单机play按钮,查看Console面板中的输出。
刚刚发生了什么
Debug. Log语句用于打印括号之间的数学算式的结果。如图所示,变量方程式使用起来与数学算式一样。
到了本章的最后,我们会讨论Unity如何将Unity如何将C#脚本转换为组件。
2.实践---更改变量的值
LearningCurve脚本的第7行声明了carDoors变量,因此可以更改其中存储的值。更新后的值会在代码中使用了carDoors变量的地方起作用,让我们看看实际效果。(1)如果场景还在运行,请单击Play按钮以停止运行。
(2)在Inspector面板中将Car Doors的值改为3,再次单击Play按钮,在Console面板查看新的输出。
注意:这里的目的不是复习变量的语法,而是演示当把变量作为容器时,,如何创建和在代码中引用变量。
疯狂的方法
就变量而言,除了跟踪指定的值之外,并不能做更多的事情。就创建有意义的应用程序而言,它们本身并不是很有用。那么,如何在代码中创建操作(action)和驱动行为囊?答案是使用方法(method).
在讨论什么是方法以及如何使用方法之前,我们需要澄清术语上的一个小问题。在编程世界里,你会看到方法和函数这两个属于经常互换使用,Unity中也不例外。C#是一门面向对象的编程语言,因此为了符合标准的C#准则,本书统一使用方法这一术语。
注意:当你在参考脚本或其他文档中遇到函数一词时,请当作方法进行理解。
方法驱动行为
与变量类似,方法的定义可能繁琐冗长,也可能十分简短。可以从下面三个方面考虑:
- 从概念上讲,方法是在应用程序中完成工作的方式
- 从技术上讲,方法是包含可执行语句的代码块,这些语句在调用方法时运行。方法可以接受参数,并且需要在方法的作用域内使用。
- 实际上,方法是每次执行时都会运行一组指令的容器。这些容器可以接收变量作为输入,这些变量只能在方法内部使用。
方法也是占位符
这个概念可以使用数字相加的例子来理解,编写脚本实际上是在设定代码行以便计算机按顺序执行,要把两个数字相加,可以像如下代码行一样简单粗暴地进行处理:
someNumber+anotherNumber
得到的结论是,当其他地方也需要把这些数字相加时,可以创建方法来处理这些行为,而不是赋值和粘贴一行代码
AddNumbers { someNumber+anotherNumber }
AddNumbers就像变量一样会分配内存,但其中存储的不是值,而是指令块。可在脚本中的任何地方使用方法名(调用指定的方法),进而执行方法中存储的指令,以免代码重复。
实践---简单方法
再次打开LearningCurve脚本,看看c#方法是如何工作的,就像之前的变量示例一样,把代码复制到脚本,为使代码更整洁,这里删掉了前面的示例代码,你也可以把代码保留在脚本中以便参考。
刚刚发生了什么
firstNumber和secondNumber这两个变量都会相加并将结果打印到控制台,如图所示,即使它们的值发生变化。
类的引入
前面已经了解了变量和类,但是编译工具仍然有一定局限性,我们需要一种方式来创建超级容器,这种容器有自己的方法和变量,于是,我们引入了类:
- 从概念上讲,类能够将相关信息,操作,行为存储到单个容器中,类之间可以相互通信
- 从技术上讲,类是数据结构,其中包含了变量和方法和其他编程信息,
- 实际上,类就是蓝图。类为创建对象制定了规则。
一直在使用类
默认情况下,Unity创建的每个脚本都是类,这可以从脚本中的class关键字看出来。
public class LearningCurve:MonoBehaviour
MonoBehaviour用于将类附加到Unity场景中的游戏对象上,C#中的类是可以单独存在的。
日常蓝图
举个示例--邮局,邮局是独立,封闭的环境,既有属性[如物理地址(变量)],也有执行行为的能力[比如发送票据(方法)].邮局是拿来诠释类的最好示例,代码如下:
postoffice { //Variables Address="1234 Letter Opener Dr." //Methods DeliverMail() SendMail() }
当信息和行为遵循预定义的蓝图,实现复杂的行为和类之间的通信变得有可能。
例如,另一个类想通过postoffic类寄信,不用考虑在哪里执行这一行为,而是可以简单地从postoffice类调用SendMail方法
postoffic.SendMail()
注释是关键
LearingCurve脚本中的注释是单行注释。VS会忽略任何以两个反斜杠开始的代码行:
//this is
没错,单行注释只能应用于一样。如果多行想要注释,则需要使用反斜杠加上星号:
实践---添加注释
vs提供了便利的自动注释功能。在任何代码行的上方键入三个反斜杠,结果如下所示:
可以看到VS自动添加了三行注释,这些注释夹在两个标签之间。可以像文本文档那样通过按Enter建来改变文本或添加新行。
将脚本附加到游戏对象上
本章介绍了编程的构成要素,在结束本章之前,下面做一些 Unity 特定的整理工作。具体来说,我们需要了解 Unity 如何处理附加到游戏
脚本成为组件
所有GameObiect组件都是脚本,而无论它们是由谁编写的。Unity 特定的组件(如Transform组件)以及它们各自的脚本是不允许我们进行编辑的。
一旦将创建的脚本拖放到游戏对象上,脚本就变成游戏对象的另一个组件,这就是脚本会出现在Inspector 面板中的原因。对于Unity而言,脚本可以像其他组件一样工作,组件的下方带有可随时更改的公共变量。即使不允许我们编辑 Unity 提供的组件,我们也可以访问它们的属性和方法,从而使它们成为强大的开发工具 。
注意:当脚本成为组件时,Uniy 还会自动进行一些可读性调整。你可能已经注意到,当把LeamingCurve 脚本附加到Main Camera 上时,Unity 会把LearningCurve脚本中的firstNumber 显示为First Number。
变量和Inspector 面板
前面的实践部分展示了如何在 Inspector 面板中更改变量,但重点是为了更深入地了解变量是如何工作的。当修改变量的值时,存在如下两种模式:
- Play模式
- 开发模式
在Play模式下,所有的更改将马上生效,这对于测试和微调游戏很有用。但需要注意的是,当停止游戏并返回开发模式时,Play模式下的所有更改都会丢失。
在开发模式下,Unity 会保存变量的所有更改。这意味着如果重启 Unity,那么之前的更改仍会保留。
注意:在 Inspector面板中,我们对变量值所做的更改不会同步更新到脚本中。更改脚本中的这些变量的唯一方法就是在 Visual Studio 中编辑它们各自的值Inspector 面板中显示的值会覆盖脚本中分配的值。
如果需要撤销在Inspector面板中所做的任何更改,可以把脚本重置为默认值(有时称为初始值)。
来自MonBehaviour的帮助
C*脚本是类,那么 Uniy 如何识别出某个脚本是组件呢? 答案很简单,LeaminCuve 脚本(以及 Unity 创建的任何脚)继承自 MonoBehaviour(这是另一类),这让Unity 获知这个C#类可以转换成组件。
类的继承对于新手来说有点难,这里可以理解为 MonoBehaviour 类将自己的一些变量和方法提供给LeamingCurve。第5章将详细介绍类的继承。
我们使用的 Start 和 Update 方法都属于 MonoBehaviour,Unity 将在任何附加到游戏对象的脚本中自动运行它们。Stat 方法会在场景开始时运行一次,而 Update 方法每帧运行一次(取决于计算机的帧率)。
类与组件通信
到目前为止,我们把类乃至 Unity 组件描述为独立的实体;事实上,它们之间确实有着紧密的联系。没有类之间的某种交互和通信,就很难创建任何有意义的应用程序。
输入点符号
是否还记得前面的邮局示例?当时,示例代码使用句点来引用类、变量和方法。如果把类当作信息目录,那么点符号相当于索引工具:
PostOffice.Address
类中的任何变量、方法或其他数据类型都可以使用点符号进行访问。这也适用于嵌套类,我们将在第5 章介绍这些主题。
点符号也能够驱动类之间的通信。当一个类需要另一个类的信息或者执行后者的方法时,就可以使用点符号:
PostOffice.DeliverMail()
类中的任何变量、方法或其他数据类型都可以使用点符号进行访问。这也适用于嵌套类,我们将在第5 章介绍这些主题。
点符号也能够驱动类之间的通信。当一个类需要另一个类的信息或者执行后者的方法时,就可以使用点符号:
PostOffice.DeliverMail()