3D游戏编程与设计–第二次做业
简答题
-
解释 游戏对象(GameObjects) 和 资源(Assets)的区别与联系。html
解答:git
- 游戏对象(GameObjects),游戏程序空间中的事物,多是 Empty(空,最有用的事物)、2D、3D、光线、摄像机等
- 游戏资源(Assets),构造游戏对象、装饰游戏对象、配置游戏的物体和数据。即序列化的或存储格式的游戏对象或数据
游戏对象指的是建立出来的对象,以及初始化时的灯光和相机。而游戏资源能够是建立的游戏对象,也能够是从外部导入的图像。github
两者也是有联系的,咱们将游戏对象拖入进游戏资源中,便成为了一个游戏资源;当咱们将游戏资源实例化以后便成为了游戏对象算法
-
下载几个游戏案例,分别总结资源、对象组织的结构(指资源的目录组织结构与游戏对象树的层次结构)编程
解答:c#
在 unity hub 中的学习目录中有不少游戏样例进行学习和下载,我选择了其中的两款进行分析。设计模式
-
经过 unity 打开后能够查看到它的 Assets 目录以下所示:数组
由图中能够看到Assets目录的结构,是采用的属性结构,父文件夹包含多个子文件夹,且相同或者相似的文件保存在同一个文件夹中,每一个子文件夹,也有若干个子文件。能够根据这样的层次结构获得结论,资源文件夹将属性类似的资源放在同一个文件夹中。框架
找到该项目的场景BlankScene打开后,能够看到对象的层次结构,不难看出有多个对象有本身的子对象,这些子对象又具备本身的子对象。父对象由他们的子对象组成起来。全部对象以树形形式组织起来。ide
-
又下载了几个游戏案例,发现其对象的层次结构与Assets的层次结构与上面的案例相似,这里就不展开说明了,直接将他们的结构截图放在下面:
- 游戏介绍:
- Assets的结构以下所示:
- 对象的层次结构以下所示:
-
-
编写一个代码,使用 debug 语句来验证 MonoBehaviour 基本行为或事件触发的条件
- 基本行为包括 Awake() Start() Update() FixedUpdate() LateUpdate()
- 经常使用事件包括 OnGUI() OnDisable() OnEnable()
解答:
首先添加一个C#代码的资源,验证的代码内容以下所示:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Test : MonoBehaviour { // Start is called before the first frame update void Start() { Debug.Log("Start"); } // Update is called once per frame void Update() { Debug.Log("Update"); } void FixedUpdate() { Debug.Log("FixedUpdate"); } void LateUpdate() { Debug.Log("LateUpdate"); } void Awake() { Debug.Log("Awake"); } void OnGUI() { Debug.Log("OnGUI"); } void OnDisable() { Debug.Log("OnDisable"); } void OnEnable() { Debug.Log("OnEnable"); } }
而后打开保存,在unity中点击play进行运行,获得的结果以下图所示:
下面是对行为或事件的解释:
- Start(): 在Update函数调用以前调用一遍
- Awake(): 用于脚本被实例装载时调用
- Update(): 每一帧都会调用一次
- FixedUpdate(): 每一个固定时间片调用一次
- LateUpdate(): 在Update函数调用后被调用
- OnGUI(): 绘制GUI时会被调用
- OnDisable(): 对象变为不可用时函数被调用
- OnEnable(): 对象变为可用状态时函数被调用
-
查找脚本手册,了解 GameObject,Transform,Component 对象
- 分别翻译官方对三个对象的描述(Description)
- 描述下图中 table 对象(实体)的属性、table 的 Transform 的属性、 table 的部件
- 本题目要求是把可视化图形编程界面与 Unity API 对应起来,当你在 Inspector 面板上每个内容,应该知道对应 API。
- 例如:table 的对象是 GameObject,第一个选择框是 activeSelf 属性。
- 用 UML 图描述 三者的关系(请使用 UMLet 14.1.1 stand-alone版本出图)
解答:
-
GameObject:Base class for all entities in Unity Scenes.(是全部在Unity场景中的实体的基类)
Transform:Position, rotation and scale of an object.(物体的位置、旋转、和大小)
Component:Base class for everything attached to GameObjects.(是全部附加到游戏物体上的基类)
-
table对象的属性:activeSelf属性,有物体的名字,和Static属性,下面是Tap,Layer,Prefab,Transform等属性
Transform的属性:Position表明物体在XYZ轴上的位置,Rotation表明物体在XYZ方向旋转的角度,Scale表示物体在XYZ方向上的大小
table的部件:Transform,Mesh Filter,Box Colider,Mesh Renderer
三者的关系是,GameObject和component是一对多的关系,也就是一个GameObject能够有多个component;GameObject和Transform是一对一的关系,也就是说一个GameObject对应于一个Transform;component是Transform的父类,Transform只是component的一种
-
资源预设(Prefabs)与 对象克隆 (clone)
- 预设(Prefabs)有什么好处?
- 预设与对象克隆 (clone or copy or Instantiate of Unity Object) 关系?
- 制做 table 预制,写一段代码将 table 预制资源实例化成游戏对象
解答:
-
预设能够快速实例化不少相同的对象,能够减小工做量,而且对于预设的修改至关因而对全部由预设建立出来的对象的修改,这样不须要一一修改,也是减小了工做量
-
用预设建立一个对象,至关因而从预设克隆出来的一个对象,对预设的所有修改,由它建立出来的全部对象都会进行修改。可是若是是克隆对象的话,因为克隆对象是相对独立的,彼此之间没有联系,也不会互相影响,因此对一个克隆对象进行改变并不会形成别的克隆对象的改变
-
首先作好Table对象,作好的成果以下所示:
作好以后将Table拖入到Assets中成为一个预制资源
成为预制资源后将原先作好的游戏对象删除掉,使得场景中只有灯光和相机两个对象,而后建立一个C#资源进行编写代码:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class NewBehaviourScript : MonoBehaviour { // Start is called before the first frame update public GameObject table; void Start() { Instantiate(table); } // Update is called once per frame void Update() { } }
将写好的C#代码加入到新建立的对象的部件中,而后点击 play 开始运行,结果以下所示:
能够看到成功将资源实例化成对象
编程实践,小游戏
-
游戏内容: 井字棋 或 贷款计算器 或 简单计算器 等等
-
技术限制: 仅容许使用 IMGUI 构建 UI
-
做业目的:
- 了解 OnGUI() 事件,提高 debug 能力
- 提高阅读 API 文档能力
我学习并制做了井字棋这个项目,实验的过程截屏以下所示:
-
游戏过程:分为两个玩家进行游戏,第一个玩家是’X’,第二个玩家是’O’,若是某个玩家的棋子3个连成一条线那么就会显示该玩家获胜,若是最终棋盘填满也没有玩家获胜,则会显示“Play even(平局)”。在游戏进行途中,或者游戏结束后均可以进行重置,只需点击左边的reset按钮便可,棋盘会从新清零,开始新的游戏
-
游戏框架:该游戏主要由9个按钮组成的棋盘,一个插入的背景图片,按钮组成的重置键,标签组成的游戏名称,以及最后游戏结束显示的结束语组成
-
代码说明:首先设置两个全局变量,int类型的board数组表明 3 * 3 的棋盘,若是数值为0表明该位置为空,若是数值为1表明玩家1在此下了棋,若为2表明玩家2在此下了棋,和int类型step变量,用于记录当前的棋盘有多少位置被下过了
而后是start()函数,包括了init()函数用来初始化棋盘,也就是清零board数组,而且将step设置为0
接下来是isWin(),函数用来判断是否有人获胜,而且返回获胜的人,若是没有人获胜则返回0
接下来就是OnGUI()函数,用来调用上面的初始化或者判断是否有人获胜,而且进行每一步下棋的操做,而且显示游戏的名称和背景,具体代码以下所示:
-
实验总结:经过本次实验学会了OnGUI函数的完成,而且学会了按钮,标签的定义过程,也更加熟悉了在游戏运行时,各个函数的运行顺序和运行次数。也发现了unity作游戏的方便之处。
-
完整实验代码:传送门
思考题【选作】
-
微软 XNA 引擎的 Game 对象屏蔽了游戏循环的细节,并使用一组虚方法让继承者完成它们,咱们称这种设计为“模板方法模式”。
- 为何是“模板方法”模式而不是“策略模式”呢?
解答:
模板方法模式:定义一个操做中算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类能够不改变一个算法的结构便可重定义该算法的某些特定步骤。是一种行为模式。
策略模式:定义一系列算法,将每个算法封装起来,并让它们能够相互替换。策略模式让算法独立于使用它的客户而变化。是一种对象行为模式。
策略模式的缺点:
-
策略类数量有可能会不少。
-
全部的策略类都须要对外暴露。
模板方法模式和策略模式均可以用来分离高层的算法和底层的具体实现细节。都容许高层的算法独立于它的具体实现细节重用。此外,策略模式也容许具体实现细节独立于高层的算法重用,不过要以一些额外的复杂性、内存以及运行时间做为代价。
-
将游戏对象组成树型结构,每一个节点都是游戏对象(或数)。
- 尝试解释组合模式(Composite Pattern / 一种设计模式)。
- 使用 BroadcastMessage() 方法,向子对象发送消息。你能写出 BroadcastMessage() 的伪代码吗?
解答:
-
组合模式(Composite Pattern),又叫部分总体模式,是用于把一组类似的对象看成一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及总体层次。这种类型的设计模式属于结构型模式,它建立了对象组的树形结构。这种模式建立了一个包含本身对象组的类。该类提供了修改相同对象组的方式。
-
// father void Start () { this.BroadcastMessage("Mes"); } // son void Mes(){ Debug.Log ("Son"); }
-
一个游戏对象用许多部件描述不一样方面的特征。咱们设计坦克(Tank)游戏对象不是继承于GameObject对象,而是 GameObject 添加一组行为部件(Component)。
- 这是什么设计模式?
- 为何不用继承设计特殊的游戏对象?
解答:
- 组合模式
- 直接添加不见,能够方便的调整对象的属性,不然可能会形成浪费现象