C#开发Unity游戏教程之游戏对象的行为逻辑方法
游戏对象的行为逻辑——方法
方法(method)。读者在第1章新建脚本时就见过了。并且在第2章对脚本做总体上的介绍时也介绍过。那么上一章呢,虽然主要内容是变量,可是在章节的最后为了展示游戏效果,也用到了它。如今看来方法真的是无处不在。并且不可或缺。它甚至都能够影响游戏对象的行为逻辑!
因此本章最终到了不得不介绍它的时候了。
Unity游戏对象的行为逻辑
游戏场景中。有些游戏对象是精巧的,比如。树木、山峰、石头等等。
而另外一些游戏对象则是运动的。它们都有自己的行为逻辑。
比如。由电脑控制的游戏对象可能会依照预定的线路行进。假设行进的途中遇到了玩家控制的游戏对象。还会发起进攻。如图4-1所看到的。行为逻辑在游戏《合金弹头》中的体现。无论是行进还是进攻。这都属于游戏对象的行为逻辑。而决定这一行为逻辑的就是脚本中的方法。
图4-1 《合金弹头》中各游戏对象的行为逻辑
Unity脚本中的方法
前两章做过两个游戏演示样例,第一个演示样例中的立方体对象会边前行边转动。第二个演示样例中的立方体则会在玩家单击指定的button后。进行移动、旋转和缩放。在这两个游戏中,立方体都表现出了特定的行为逻辑,而决定这些行为逻辑的就是方法。如图4-2所看到的的是第一个游戏演示样例中的脚本方法。
图4-2 脚本中决定游戏对象行为逻辑的方法
上一章的末尾向读者介绍过语句,那么再来看脚本中的方法,它的外在表现形式就是由一条或多条语句组成的。通常情况下,脚本中声明的变量是用来存储数据的,而脚本中的方法则会对这些数据做一些处理,然后将这些数据应用到游戏对象行为逻辑的控制中。比如。上一章演示的演示样例。通过在Inspector视图里调节属性的值,进而影响到立方体对象的缩放大小,如图4-3所看到的。
图4-3 脚本中的方法,将属性中的数据应用到对游戏对象行为逻辑的控制中
Unity中使用脚本方法
通过本章前面的介绍,读者或许已经认识到了方法是有多重要,以至于前面两章介绍的游戏演示样例。都必须在方法的协助下,才实现了终于的效果。方法这么奇妙,读者如今一定有兴趣来了解。那么本节就来逐步揭开方法的神奇面纱。
Unity中的方法与变量
方法与变量有非常多相似的地方。比如,变量与变量名不等价。方法与方法名相同如此。
详细的说明例如以下:
-
q 方法也是一块儿特定的存储空间,仅仅只是方法里存储的不是数据,而是代码语句;
-
q 方法名也须要遵守C#的命名规则,即名称必须由字母、数字和下划线组成。且数字不能作为名称的首字母。否则就是犯了语法错误;
-
q 为了差别方法名与变量名。读者能够考虑遵守这样一个约定。即变量名的首字母小写,方法名的首字母大写。既然说这是一个约定,读者当然能够不遵守,也不会犯语法错误;
-
q 就像是变量名一样,方法名也应该取的有意义些。
比如,既然方法能够控制游戏对象的逻辑行为。那么就能够考虑给控制立方体移动的方法定一个类似于CubeWalking的方法名。
-
q 相同能够使用public和private修饰,仅仅只是方法使用什么修饰,结果都不会体如今Inspector视图中,仅仅是会反应在对方法的使用上。
即使用public修饰的方法,能够被其他脚本使用。而使用private修饰,则正好相反。假设省略了对方法的修饰。Unity会觉得方式是被private修饰的。
Unity中定义方法
就像是在使用变量前须要声明变量一样。用法前,须要定义方法。
这就像是在告诉Unity:存在这样一个方法,此方法能够控制游戏对象做出特定的行为。方法的定义形式例如以下:
-
返回值类型 方法名()
-
{
-
//方法中的语句
-
}
-
q 方法名后的一对括号“( )”是不可缺少的;
-
q 被大括号“{ }”括住的语句。就能够看作是存储于方法中的数据;
-
q 声明变量时。有些读者注意到,它的末尾是以分号“;”结尾的。可是对于方法的定义。大括号里的“}”就是结束标识,读者无需“画蛇添足”;
-
q 方法能够“返回特定类型的数据”。
比如,前面章节编写游戏时,用到的脚本中的一个方法例如以下:
-
void Update()
-
{
-
transform.Translate(new Vector3(xPosition,0,0),Space.World);
-
transform.Rotate(Vector3.up*yRotation,Space.World);
-
}
对于此方法,Unity会这样理解:
-
q 这种方法名为Update()。
-
q 方法中一共同拥有两条语句。
-
q 方法返回的数据类型是void。此类型表示方法不会返回不论什么值。
因此。与其说void表示一种类型。还不如说它是一种标志,即不返回不论什么类型数据的标志。
-
q 省略了对方法的修饰。因此Unity会觉得它是被private修饰的。因此其他脚本无法使用这种方法;
Unity中调用方法
方法定义好以后,就能够直接使用了。
用法在脚本中有个专门术语。就是“调用方法”。
在脚本中调用方法的方式非常easy,直接用法名就能够了。可是千万不要忘了带上后面的一对括号“( )”。
例如以下:
-
//方法的定义部分
-
… //省略
-
//调用方法
-
AddTwoNumber();
Unity中方法使用演示样例
理论部分已经写了非常多,读者应该对方法的概念有印象了才对。
那如今就趁热打铁。以一个演示样例来说明方法的定义和调用。实现演示样例的操作过程例如以下:
(1)在Project视图里,新建一个脚本文件,命名为MyScript,打开此脚本文件并加入以下的代码:
-
01 using UnityEngine;
-
02 using System.Collections;
-
03
-
04 public class MyScript : MonoBehaviour
-
05 {
-
06 private int number1 = 15;
-
07 private int number2 = 59;
-
08 void OnGUI()
-
09 {
-
10 GUILayout.Label ("number1 = " + number1);
-
11 GUILayout.Label ("number2 = " + number2);
-
12 GUILayout.Label ("number1 + number2 = " + AddTwoNumber ()); //用法
-
13 }
-
14 int AddTwoNumber() //定于方法
-
15 {
-
16 return number1 + number2;
-
17 }
-
18 }
对于此脚本的06、07行代码,读者一定不陌生。这里的代码完毕了变量的声明和初始化。
变量是上一章重点介绍的内容,而本章主要关心14~17行方法的定义部分。以及12行方法的调用部分。
-
q 从方法的定义上来看,方法名为AddTwoNumber(),会返回int类型的数据。方法里仅仅有一行语句,语句的含义是计算两个整数的和。
-
q 从方法的调用上来看,用法的方式非常easy,直接书写AddTwoNumber()就能够了。
(2)将脚本MyScript加入到Main Camera对象上,除此以外游戏场景中不须要不论什么其他游戏对象。直接执行游戏。在游戏视图的左上角会出现3行文本信息,如图4-4所看到的。
图4-4 游戏视图左上角的文本信息
(3)这仅仅是一个演示样例。是让读者熟悉方法定义和调用的演示样例。所以没有让方法控制游戏对象的行为逻辑,至于方法的游戏演示样例,会在本章兴许内容解说结束以后给出。
Unity内置的方法
在Unity中新建的脚本文件,里面会自己主动加入一些代码,如图4-5所看到的。
读者在学习完方法以后,有没有认为自己主动加入的代码中。Start()和Update()的书写形式非常像方法。没错,它们就是方法。仅仅只是它们是Unity内置的方法。他们会被游戏程序调用。
图4-5 脚本中Unity自己主动加入的代码
由于这两个方法在脚本中非经常常使用。所以Unity直接在新建的脚本中加入了它们。那么。读者可能要问了,这两个方法会怎样作用于游戏对象呢?代码中使用了凝视(双斜杠“//”以及后面的部分就是凝视)对这两个方法进行了简单的说明:前者在初始化时被调用,后者在游戏执行过程的每一帧被调用。假设读者并不满足于凝视上的解释,能够考虑查阅Unity的帮助文档。在第1章中。作者介绍过帮助文档的打开和检索方式。忘了的话能够去复习下面。
现以查找Start()方法的使用说明为例。在帮助文档的检索框中输入MonoBehaviour.start,開始查找。普通情况下会查找出非常多结果,选择须要的结果,打开它就能够了。整个过程如图4-6所看到的。
在帮助文档中。会首先对这种方法的功能和使用步骤做简要说明,并在最后给出这种方法的使用演示样例。
提示:Unity 的脚本能够使用三种语言编写。它们是C#、JavaScript和Boo。因此帮助文档会给出分别使用这3种语言的使用演示样例。由于本书解说时使用的语言是C#,所以建议读者看C#语言编写的演示样例。
图4-6 使用Unity提供的帮助文档,查看Start()方法的使用说明
以下使用一个演示样例来说明,Unity内置方法Start()和Update()的使用。
演示样例的操作过程例如以下:
(1)打开脚本MyScript,为其加入以下的代码:
-
01 using UnityEngine;
-
02 using System.Collections;
-
03
-
04 public class MyScript : MonoBehaviour
-
05 {
-
06 private int frameCount = 0;
-
07 void Start()
-
08 {
-
09 Debug.Log ("这是Start()里输出的信息");
-
10 }
-
11 void Update()
-
12 {
-
13 frameCount++;
-
14 if(frameCount == 100)
-
15 {
-
16 Debug.Log ("这是Update()里输出的信息");
-
17 frameCount = 0;
-
18 }
-
19 }
-
20 }
新加入的代码,分别为Start()和Update()加入了一条语句(09行)和多条语句(13~18行),实现的功能均是在Unity的Console视图里输出一行文本信息。
读者能够从输出的信息中了解到,Start()和Update()的调用情况。
(2)执行游戏,这次观察的焦点不是Game视图。而是Console视图。输出的文本信息,如图4-7所看到的。
图4-7 Console视图的文本信息输出结果
通过Unity提供的帮助文档。读者应该了解到,方法Start()是在游戏对象初始化的时候调用,且是在Update()前被调用。因此,Console视图中首先输出的是Start()方法里的文本信息,而后Update()方法才被调用。因此随后就输出了Update()方法里的文本信息。
而且,因为Update()方法在每帧都会被调用,因此Update()方法里的文本信息会在游戏执行的过程中,持续输出。
提示:假设让Update()方法每帧都输出信息的话,Console视图非常快就会被“刷屏”了。为了阻止这样的现象的发生。脚本代码仅仅是让Update()方法每100帧输出一次文本信息,可是Update()方法依旧在每帧被调用。
Unity中的方法的參数
出如今脚本中的方法。不管是在定义的时候。还是使用的时候。后面都跟着一对括号“( )”,有意义吗?看起来最多也就是起个高速识别方法的作用吧。
既然C#的语法规定方法就应该这么写。肯定是有一定道理的。假设是上升到战略意义的道理,连作者也不是非常明确,可是作者知道这对括号中能够加入“參数”。
Unity中參数的作用
要说明參数的作用,就必须从方法说起。方法能够处理变量中的数据,进而影响游戏对象的行为逻辑,这是本章前面一直在强调的。
可是就前面脚本中一直在使用的。方法的括号中没有參数的情况而言。方法总是在处理特定变量里的数据。比如。以下是前面一个演示样例中定义的方法:
-
int AddTwoNumber()
-
{
-
return number1 + number2;
-
}
这种方法的括号中没有參数,它处理的数据总是变量number1和number2里的数据。既然这仅仅是一个用于求和的方法。没有必要指定它仅仅计算变量number1和number2里的数据和。假设有其他变量的数据也要求和的话,就仅仅能再定义一个方法了。为方法引入參数就能够非常好的解决这类的问题。
对于游戏的实际意义
开发人员定义了一个方法。能够控制一个游戏对象的逻辑行为。
假设其他对象也须要做出与之类似的行为。就没有必要再定义一个方法了。比如以下的游戏演示样例所做的那样。
(1)为游戏场景加入Cube、Cylinder和Directional light,这3个游戏对象。
前两者将作为脚本方法控制行为逻辑的游戏对象,最后一个游戏对象负责游戏场景的照明。
合理设置它们各自的位置,得到的Scene和Game视图。如图4-8所看到的。
图4-8 在Scene和Game视图里,查看各对象的相对位置。以及游戏视图的效果
(2)在Project视图里,新建脚本文件。命名为MyScript。打开此脚本并加入以下的代码:
-
01 using UnityEngine;
-
02 using System.Collections;
-
03
-
04 public class MyScript : MonoBehaviour
-
05 {
-
06 public GameObject myCube;
-
07 public GameObject myCylinder;
-
08 void OnGUI()
-
09 {
-
10 //当鼠标左键按下的时候
-
11 if(Input.GetMouseButton(0))
-
12 RotateObject (myCube);
-
13 //当鼠标右键按下的时候
-
14 if(Input.GetMouseButton(1))
-
15 RotateObject (myCylinder);
-
16 }
-
17 //改变游戏对象朝向的方法
-
18 void RotateObject(GameObject myObject)
-
19 {
-
20 myObject.transform.Rotate(Vector3.right*100,Space.World);
-
21 }
-
22 }
-
q 脚本代码的18~21行,是有參数方法的定义部分。从代码来看,传入的參数是一个游戏对象,而方法中的语句。就是通过改动游戏对象Transform组件下的Rotation属性。实现改变游戏对象朝向的目地的。
-
q 脚本代码的12、15行,调用了两次方法RotateObject(),先后传入的參数也是不一样的;
(3)将脚本MyScript赋予Main Camera对象。并在后者的Inspector视图里,设置My Script组件里的My Cube和My Cylinder属性为游戏场景中的Cube和Cylinder对象。属性的设置方法是,直接拖动Hierarchy视图里的Cube和Cylinder对象到相应的属性框中就可以,如图4-9所看到的。
图4-9 设置My Script组件下的属性
(4)执行游戏。在Game视图里,一直按下鼠标左键,读者会看到立方体对象在原地滚动。
假设一直按下鼠标右键。那么原地滚动的就成了圆柱体。假设同一时候按住鼠标左键和右键。立方体和圆柱体就会同一时候滚动了,如图4-10所看到的。
图4-10 游戏效果展示图
(5)游戏中,控制游戏对象滚动的方法是RotateObject(),它是一个须要传入參数的方法。正是由于须要传入參数。所以它才干被用于游戏场景中。全部游戏对象滚动的行为逻辑控制中。而不仅仅是单独的控制一个对象的行为逻辑。
本文选自:C#游戏开发高速入门大学霸内部资料。转载请注明出处,尊重技术尊重IT人!