作业内容
一、简答题
- 解释游戏对象(GameObjects)和资源(Assets)的区别与联系。
- 区别
游戏对象:对象是具有一定属性与功能的事物的实体化。游戏对象就是在游戏过程中承担一部分职能并携带一定属性的组件,例如游戏角色、怪物、BOSS、地形等等。
资源:资源即素材,可以在不同地方重复使用。 - 游戏对象与资源的关系类似于对象实例与类的关系
资源是对象的模板,从一个资源可以方便地创建任意多个具有相同属性的对象。 - 对资源的修改会影响所有对应的对象
一个对象一旦与某个资源绑定,或者由该资源被创建,则对资源的修改会反应到该对象上。不过,对象也可以显式地与资源解除绑定,之后资源就再也影响不到这个对象了。
- 下载几个游戏案例,分别总结资源、对象组织的结构(指资源的目录组织结构与游戏对象树的层次结构)
太阳系
- 资源的目录组织结构
Models 模型文件
Plugins 主要是DLL的外部插件文件
Prefabs 预储存文件
Resources 动态加载的资源文件
Scenes 场景文件
Scripts 脚本代码文件
Sounds 音效文件
Textures 所有的贴图 - 对象树的层次结构
-
编写一个代码,使用debug语句来验证MonoBehaviour基本行为或事件触发的条件
- 基本行为包括 Awake() Start() Update() FixedUpdate() LateUpdate()
- 常用事件包括 OnGUI() OnDisable() OnEnable()
- 代码
public class TestBeh : 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");
}
private void Awake()
{
Debug.Log("Awake");
}
private void FixedUpdate()
{
Debug.Log("FixedUpdate");
}
private void LateUpdate()
{
Debug.Log("LateUpdate");
}
private void OnGUI()
{
Debug.Log("OnGUI");
}
private void OnDisable()
{
Debug.Log("OnDisable");
}
private void OnEnable()
{
Debug.Log("OnEnable");
}
}
- 运行结果
通过简单分析可知,游戏开始运行时,最先执行的行为是Awake,紧接着OnEnable事件被触发,随后是Start行为,接下来Update、FixedUpdate和LateUpdate被多次地执行,与此同时OnGUI间歇地被触发。游戏结束时OnDisable被触发。
-
查找脚本手册,了解 GameObject,Transform,Component 对象
- 分别翻译官方对三个对象的描述(Description)
- GameObject:Unity场景中所有实体的基类
- Transform:物体的位置,旋转角度及比例
- Component:所有附加在GameObject上的事物的基类
-
描述下图中 table 对象(实体)的属性、table 的 Transform 的属性、 table 的部件
- 本题目要求是把可视化图形编程界面与 Unity API 对应起来,当你在 Inspector 面板上每一个内容,应该知道对应 API。
- 例如:table 的对象是 GameObject,第一个选择框是 activeSelf 属性。
- 属性
table 的对象是 GameObject,第一个选择框是 activeSelf 属性。
table的标签(tag)没有被设置,可以通过下拉选项从已有标签中选择一个或者自定义一个新的标签,一旦设置则table可以被其他对象通过标签名识别。
table的图层(layer)被设置为默认图层,可以通过修改这个属性实现多个对象的分离(在处理碰撞事件时很有用)。
open按键对应打开table对应的预制;select按键对应为table选择预制。 - transform属性
由上到下三行分别可以设置table对象的三维坐标、三个轴向上的旋转角度,三个轴向上的长度。 - table部件
在transform下方的内容都是描述table的部件,包括materials(材料)、Lighting(光照)、Box Collider(碰撞机)等等。可以通过add Component添加新的部件,并且在每个部件对应的区域内可以调节其属性。
- 用 UML 图描述 三者的关系(请使用 UMLet 14.1.1 stand-alone版本出图)
-
资源预设(Prefabs)与 对象克隆 (clone)
- 预设(Prefabs)有什么好处?
预设可以多次重复使用,用于创建多个相同的对象;
通过预设管理多个对象,可以简化操作 - 预设与对象克隆 (clone or copy or Instantiate of Unity Object) 关系?
通过预设创建新对象与通过克隆创建新对象是两种创建新对象的方法,但它们是有区别的。通过预设创建的对象与预设之间有直接的联系,而克隆产生的是一个全新的对象,它不与产生它的对象之间有任何联系(即其中一个的变化不会影响另一个,它们是完全独立的)。 - 制作 table 预制,写一段代码将 table 预制资源实例化成游戏对象
以课堂上做过的练习为例,通过预制砖块(brick)建造一堵墙
- 预设(Prefabs)有什么好处?
BuildWall的代码如下:
public class BuildWall : MonoBehaviour
{
public Transform brick;
// Start is called before the first frame update
void Start()
{
for (int i = -2; i < 3; ++i) {
for (int j = -5; j < 6; ++j) {
GameObject newobj = Instantiate<Transform> (brick, this.transform).gameObject;
newobj.transform.position = new Vector3 (i, (float)0.25 * j, 0);
}
}
}
// Update is called once per frame
void Update()
{
}
}
运行结果:
二、编程实践,小游戏
- 游戏内容: 井字棋 或 贷款计算器 或 简单计算器 等等
- 技术限制: 仅允许使用 IMGUI 构建 UI
- 作业目的:
- 了解 OnGUI() 事件,提升 debug 能力
- 提升阅读 API 文档能力
为减少此篇博客的篇幅,将这一部分的作业内容放在另一篇博客上。
井字棋博客链接
三、思考题【选做】
-
微软 XNA 引擎的 Game 对象屏蔽了游戏循环的细节,并使用一组虚方法让继承者完成它们,我们称这种设计为“模板方法模式”。
- 为什么是“模板方法”模式而不是“策略模式”呢?
策略模式和模板模式有一个最重要的区别,即模板模式一般只针对一套算法,注重对同一个算法的不同细节进行抽象提供不同的实现。而策略模式注重多套算法多套实现,在算法中间不应该有交集。
显然游戏循环是大同小异的,不存在算法上的根本分歧,只是对同一算法的不同实现,所以更接近与模板模式。
- 为什么是“模板方法”模式而不是“策略模式”呢?
-
将游戏对象组成树型结构,每个节点都是游戏对象(或数)。
- 尝试解释组合模式(Composite Pattern / 一种设计模式)。
组合模式把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。 - 使用 BroadcastMessage() 方法,向子对象发送消息。你能写出 BroadcastMessage() 的伪代码吗?
- 尝试解释组合模式(Composite Pattern / 一种设计模式)。
void BroadcastMessage(string str) {
receive(str)
for child : childList :
BroadcastMessage(str)
}
- 一个游戏对象用许多部件描述不同方面的特征。我们设计坦克(Tank)游戏对象不是继承于GameObject对象,而是 GameObject 添加一组行为部件(Component)。
- 这是什么设计模式?
桥接模式。 - 为什么不用继承设计特殊的游戏对象?
桥接模式将继承关系转化成关联关系,它降低了类与类之间的耦合度,减少了系统中类的数量,也减少了代码量。
以一个图形类为例,假设一个图形可以有三种不同形状、三种不同颜色,如果以传统继承的方法,我们需要为不同颜色的相同形状分别创建一个类,所以总共有3*3=9个类;如果采用桥接的方法,我们可以先创建一个颜色类和一个形状类,它们分别包含3个子类,然后在创建具体的对象类时从形状类和颜色类中分别选一个类继承。桥接的优点是系统中类的数量更少,类的创建更灵活,如果我们不需要黑色长方形,那么这个类就不会被创建(只会有黑色、长方形)。
另一方面,将不同部件的类分离也更有利于维护。如果现在要在原来基础上新增一种颜色,桥接模式中只需要新增一个颜色的子类即可,而继承则需要“大动干戈”,为每一个形状都加上对应新颜色的类。
- 这是什么设计模式?