简答题
1. 解释游戏对象(GameObjects) 和资源(Assets)的区别与联系。
游戏对象(GameObjects) 指的是游戏中一个可被选中的对象,比如一个方块,一幅平面、一位角色形象等。对象可以被赋予一些属性,进而完成某些动作。
而资源(Assets) 则是一个游戏项目中的素材,比如音频、视频、脚本文件、模型等。
它们之间的联系是,资源可以被实例化成游戏对象,游戏对象也可以被保存为资源。一个资源可以被多个游戏对象使用,也可能不被任何对象使用。
2. 下载几个游戏案例,分别总结资源、对象组织的结构(指资源的目录组织结构与游戏对象树的层次结构)
资源目录下,根据资源的性质(Plugins,Code,Scene…),分成几个子目录,分别存放不同类型的资源。
子目录下再进行分类(比如Resource目录下的Effect,Image,Runtime…)方便对资源进行管理。
游戏对象的结构如下,可以看到这个游戏中有camera,Root,EventSystem,BDFrame等对象
3. 编写一个代码,使用 debug 语句来验证 MonoBehaviour 基本行为或事件触发的条件
- 基本行为包括 Awake() Start() Update() FixedUpdate() LateUpdate()
- 常用事件包括 OnGUI() OnDisable() OnEnable()
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : 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 Awake()
{
Debug.Log("Awake");
}
void FixedUpdate()
{
Debug.Log("FixedUpdate");
}
void LateUpdate()
{
Debug.Log("LateUpdate");
}
void OnGUI()
{
Debug.Log("onGUI");
}
void OnDisable()
{
Debug.Log("onDisable");
}
void OnEnable()
{
Debug.Log("OnEnable");
}
}
运行结果:
4. 查找脚本手册,了解 GameObject,Transform,Component 对象
- 分别翻译官方对三个对象的描述(Description)
游戏对象 是代表人物、道具和场景的基本对象。它们本身并没有完成多少工作,但是它们充当组件的容器,组件实现真正的功能。
Transform 组件决定场景中每个对象的位置、旋转和比例。每个游戏对象都有一个Transform。
Component 是游戏中对象和行为的螺母和螺栓。它们是每个游戏对象的功能部件。
-
描述下图中 table 对象(实体)的属性、table 的 Transform 的属性、 table 的部件
- 本题目要求是把可视化图形编程界面与 Unity API 对应起来,当你在 Inspector 面板上每一个内容,应该知道对应 API。
- 例如:table 的对象是 GameObject,第一个选择框是 activeSelf 属性。
table的属性:activeInHierarchy(对象在当前场景中是否为active),ObjectName,activeSelf(对象在本地是否为active),Tag,Layer,prefabs(预设)
transform的属性:Position,Rotation,Scale
table的部件:Mesh Filter,Box Collider,Mesh Renderer -
用 UML 图描述 三者的关系(请使用 UMLet 14.1.1 stand-alone版本出图)
5. 整理相关学习资料,编写简单代码验证以下技术的实现:
-
查找对象
``` //按照名字对象名查找 public static GameObject Find(string name) //按照标签查找单个对象 public static GameObject FindWithTag(string tag) //按照标签查找多个对象 public static GameObject[] FindGameObjectsWithTag(string tag) ```
-
添加子对象
public static GameObect CreatePrimitive(PrimitiveTypetype)
-
遍历对象树
foreach (Transform child in transform) { Debug.Log(child.gameObject.name); }
-
清除所有子对象
foreach (Transform child in transform) { Destroy(child.gameObject); }
-
8. 资源预设(Prefabs)与 对象克隆 (clone)
- 预设(Prefabs)有什么好处?
- 预设相当于模板,方便我们创建具有相同属性和行为的对象。
- 预设方便管理对象。当同一类型的对象需要改变某些属性时,我们只需要修改它们的预设即可。
- 预设与对象克隆 (clone or copy or Instantiate of Unity Object) 关系?
- 克隆必需是在已经存在一个对象的情况下,克隆出另外一个对象;而预设可以创造一个原先不存在的对象。
- A由B克隆得到,则B发生改变不会影响A;而预设发生改变时会影响所有创建的对象。
-
制作 table 预制,写一段代码将 table 预制资源实例化成游戏对象
public GameObject table; void Start () { Debug.Log("Init Start"); GameObject newTable = (GameObject)Instantiate(table.gameObject); }
编程实践
-
游戏内容: 井字棋 或 贷款计算器 或 简单计算器 等等
-
技术限制: 仅允许使用 IMGUI 构建 UI
-
作业目的:
- 解 OnGUI() 事件,提升 debug 能力
- 提升阅读 API 文档能力
作业链接:https://github.com/akanine/Unity3d_TicTacToe/tree/master
井字棋是一种在3*3棋盘上完成的连珠游戏,类似于五子棋
实现效果如下:
思考题
- 微软 XNA 引擎的 Game 对象屏蔽了游戏循环的细节,并使用一组虚方法让继承者完成它们,我们称这种设计为“模板方法模式”。
- 为什么是“模板方法”模式而不是“策略模式”呢
模板方法模式是类的行为模式。准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后生命一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。这就是模板方法模式的用意。
策略模式定义一组算法,这组算法实现了相同的接口或者继承相同的抽象类。将每一个算法封装起来,从而使它们可以相互切换。
策略模式是对象的行为模式。
微软XNA引擎的Game对象实际上是一组抽象类,因为它“屏蔽了游戏循环的细节,而使用虚方法让继承者完成细节”。符合模板方法模式的意图,增强了game对象的拓展性,且使其易于维护;而策略模式的关键意图在于封装相似的算法使它们可以互相替换,但这样会导致策略类繁多和暴露,不符合game对象的设计要求。
- 将游戏对象组成树型结构,每个节点都是游戏对象(或数)。
- 尝试解释组合模式(Composite Pattern / 一种设计模式)。
组合模式用树形结构来组合对象,表示部分以及整体的层次。把一组相似的对象当成一个单一对象,使用户对单个对象和组合对象的使用具有一致性。使复杂元素的内部解耦、节点可自由增加、调用简单。
-
使用 BroadcastMessage() 方法,向子对象发送消息。你能写出 BroadcastMessage() 的伪代码吗?
public class NewBehaviourScript : MonoBehaviour { void message() { Debug.Log("HelloWorld!"); } void Start () { this.BroadcastMessage("parent"); } }
public class NewBehaviourScript1 : MonoBehaviour { void message() { Debug.Log("HelloWorld!"); } }
-
一个游戏对象用许多部件描述不同方面的特征。我们设计坦克(Tank)游戏对象不是继承于GameObject对象,而是 GameObject 添加一组行为部件(Component)。
- 这是什么设计模式?
装饰器模式 - 为什么不用继承设计特殊的游戏对象?
- 采用装饰器模式,装饰类和被装饰类可以独立发展,不会相互耦合
- 继承会增加过多的子类
- 继承不能方便地动态添加/撤销功能
- 这是什么设计模式?