作业内容
简答题
1.解释游戏对象(GameObjects)和资源(Assets)的区别与联系。
游戏对象:在游戏场景中出现的物体都是游戏对象。
资源:游戏项目中的素材,可以包括模型、图形、音频、脚本等。
联系:游戏对象可以保存为资源,资源可以实例化为游戏对象。
2.下载几个游戏案例,分别总结资源、对象组织的结构(指资源的目录组织结构与游戏对象树的层次结构)
只能找到资源的结构,游戏对象树网络上没找到。
总的来说,资源的目录组织结构主要包含文件、材质、模型、预制件、场景、脚本、标准资源这几个部分。资源里面又包含了图片,游戏需要用到的音乐等等。
游戏对象树就如同Windows的文件资源管理器一样,树目录结构:一个游戏对象(文件夹)包含多个子对象(子文件夹),子对象(子文件夹)又可以继续包含多个子对象(子文件夹)
3.编写一个代码,使用 debug 语句来验证MonoBehaviour 基本行为或事件触发的条件
-
基本行为包括 Awake() Start() Update() FixedUpdate() LateUpdate()**
-
常用事件包括 OnGUI() OnDisable() OnEnable()**
代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class testBehavior : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
Debug.Log("Start");
}
void Awake()
{
Debug.Log("Awake");
}
// Update is called once per frame
void Update()
{
Debug.Log("Update");
}
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");
}
}
运行结果图如下:
start函数:在所有update函数调用之前调用一次;
awake函数:主要用于一个脚本被实例装载时调用;
Update函数:当对象可见时,每帧都执行一次(每一帧的时间不固定);
FixedUpdate函数:当对象可见时,每固定时间片执行一次(每帧与每帧之间相差的时间是固定的);
LateUpdate函数:在所有Update函数调用后被调用。可用于调整脚本执行顺序。例如:当物体在Update里移动时,跟随物体的相机可以在LateUpdate里实现;
OnGUI函数:绘制GUI时候触发。一般在这个函数里绘制GUI菜单;
OnDisable函数: 当对象变为不可用或非激活状态时此函数被调用。
OnEnable函数:当对象变为可用或激活状态时此函数被调用。
4.查找脚本手册,了解 GameObject,Transform,Component 对象
-
分别翻译官方对三个对象的描述(Description
GameObject:是Unity场景里面所有实体的基类.
Transform:物体的位置、旋转和缩放。
Component:一切附加到游戏物体的基类。 -
描述下图中 table 对象(实体)的属性、table 的 Transform 的属性、 table 的部件
第一个选择框是activeSelf:可以定义对象的名称,动静态等属性,比如上图,对象名称是table
第二个选择框是Transform:可以定义对象的位置、面向方向、大小
第三个选择框是Box Collider:可以调整坐标系的位置、大小
第四个选择框是Add Component:可以给对象增加行为,比如给对象增加C#script
-
5.整理相关学习资料,编写简单代码验证以下技术的实现:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Find : MonoBehaviour { // Use this for initialization void Start () { GameObject find1 = GameObject.Find ("chair1"); if (find1 == null) { Debug.Log ("Can't find chair1"); } else { Debug.Log ("Find chair1"); } GameObject find2 = GameObject.Find ("chair5"); if (find2 == null) { Debug.Log ("Can't find chair5"); } else { Debug.Log ("Find chair5"); } } // Update is called once per frame void Update () { }
运行结果如下
总的来说,查找对象有两种方法,根据名字、标签//通过名字查找 public static GameObject Find(string name); //通过标签查找单个对象 public static GameObject FindWithTag(string tag); //通过标签查找多个对象 public static GameObject[] FindGameObjectsWithTag(string tag);
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Create : MonoBehaviour { public GameObject table; // Use this for initialization void Start () { GameObject createCube = GameObject.CreatePrimitive(PrimitiveType.Cube); createCube.name = "cube2"; createCube.transform.position = new Vector3(0, Random.Range(0, 5), 0); createCube.transform.parent = this.transform; GameObject table2 = GameObject.Instantiate (table); table2.name = "table2"; table2.transform.position = new Vector3(3, Random.Range(0, 5), 0); table2.transform.parent = this.transform; } // Update is called once per frame void Update () { } }
这里创建了两个对象,一个是Cube,一个是预制得到的table,首先将代码拖到CreateObj这个空对象里
会发现component一项的Table是空的,将Assets中的table拖入即可,然后点击运行,就会发现CreateObj对象里多出了两个子对象,一个叫cube2,一个是table2
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Traverse : MonoBehaviour { // Use this for initialization void Start () { foreach(Transform child in transform){ Debug.Log(child.name); } } // Update is called once per frame void Update () { } }
运行结果
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Delete : MonoBehaviour { // Use this for initialization void Start () { foreach (Transform child in transform) { Destroy(child.gameObject); } } // Update is called once per frame void Update () { } }
运行前:
运行后:
6.资源预设(Prefabs)与 对象克隆 (clone)
-
预设(Prefabs)有什么好处?
预设可以快速实例化大量的相同的游戏对象,先代码量少,而且想要修改通过预设实例化出来的游戏对象,无需一一修改,只需要修改预设,就可以全部一同修改了。 -
预设与对象克隆 (clone or copy or Instantiate of Unity Object) 关系
预设实例化的游戏对象就好像只是引用了预设而已,共享预设的一切属性,如果预设被修改了,所有通过预设实例化的游戏对象都会被改变;克隆是复制一个一模一样的游戏对象,它们之间独立,互不干扰,修改任一一个游戏对象,也不会改变其他的克隆游戏对象。 -
制作 table 预制,写一段代码将 table 预制资源实例化成游戏对象
首先在一个场景里面画好一个table
然后将左边框里的游戏对象table拖动到Assets中,即可制得table预制
编程实践,小游戏
-
游戏内容: 井字棋 或 贷款计算器 或 简单计算器 等等
-
技术限制: 仅允许使用 IMGUI 构建 UI
-
作业目的:
1.了解 OnGUI() 事件,提升 debug 能力
2.提升阅读 API 文档能力
项目传送门
思考题
-
微软 XNA 引擎的 Game 对象屏蔽了游戏循环的细节,并使用一组虚方法让继承者完成它们,我们称这种设计为“模板方法模式”。
模板方法模式:定义一个操作中算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。是一种行为模式。
策略模式:定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化。是一种对象行为模式。模板方法更加强调:
1)定义一个算法流程,这个流程上的多个点是可以变化的(具体实现在子类中完成),流程上的多个点一定是会被执行的,并且一定是按照特定流程被执行的。
2)算法流程只有唯一的入口,对于点的访问是受限的;
而策略模式更注重于: 一个“策略”是一个完整的算法,算法是可以被整体替换的。而模板方法只能被替换其中的特定点,算法流程是固定不可变的。 -
将游戏对象组成树型结构,每个节点都是游戏对象(或数)。
组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。
-
使用 BroadcastMessage() 方法,向子对象发送消息。你能写出 BroadcastMessage() 的伪代码吗?
父对象代码
子对象代码using System.Collections; using System.Collections.Generic; using UnityEngine; public class Father : MonoBehaviour { // Use this for initialization void Start () { this.BroadcastMessage("test"); } // Update is called once per frame void Update () { } }
将Father的拖到table中,Son拖到chair1中,点击运行观看控制台输出using System.Collections; using System.Collections.Generic; using UnityEngine; public class Son : MonoBehaviour { // Use this for initialization void Start () { } // Update is called once per frame void Update () { } void test(){ Debug.Log ("Hello, father"); } }
-
-
一个游戏对象用许多部件描述不同方面的特征。我们设计坦克(Tank)游戏对象不是继承于GameObject对象,而是 GameObject 添加一组行为部件(Component)。