解释 游戏对象(GameObjects) 和 资源(Assets)的区别与联系。
区别
游戏对象(GameObjects)
游戏中的物体就是游戏对象,例如游戏中的角色、道具和环境物体。游戏对象都是由空对象构建而成的。通过向空对象中加入不同的属性(组件),我们可以获得具有不同外观和行为的游戏对象。
资源(Assets)
游戏开发过程中需要的资源包括材质、纹理、模型、动画、预设、音频、场景等,是能应用在游戏中的素材。
联系
资源能够被导入到游戏中,被游戏对象使用,影响游戏对象的属性。资源还可以被用来创建新的游戏对象。
下载几个游戏案例,分别总结资源、对象组织的结构(指资源的目录组织结构与游戏对象树的层次结构)
Unity 官方教程的资源目录组织和游戏对象树如下:
游戏资源被放到不同的层级中,层次和内容十分清晰。游戏对象间也有明确的层级关系,以便实现游戏中的组合模式。
编写一个代码,使用 debug 语句来验证 MonoBehaviour 基本行为或事件触发的条件
- 基本行为包括 Awake() Start() Update() FixedUpdate() LateUpdate()
- 常用事件包括 OnGUI() OnDisable() OnEnable()
代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70// C# Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour {
// 判断是否执行过相应函数
private bool isUpdate = false;
private bool isFixedUpdate = false;
private bool isLateUpdate = false;
private bool isOnGUI = false;
// 当一个脚本实例被载入时 Awake 被调用
void Awake () {
Debug.Log ("Awake");
}
// Start 仅在 Update 函数第一次被调用前调用
void Start () {
Debug.Log ("Start");
}
// 当 MonoBehaviour 启用时,其 Update 在每一帧被调用
void Update () {
// 确保函数只被执行一次
if (!isUpdate) {
Debug.Log ("Update");
isUpdate = true;
}
}
// 当 MonoBehaviour 启用时,其 FixedUpdate 在每一帧被调用
void FixedUpdate () {
// 确保函数只被执行一次
if (!isFixedUpdate) {
Debug.Log ("Fixed Update");
isFixedUpdate = true;
}
}
// 当 Behaviour 启用时,其 LateUpdate 在每一帧被调用
void LateUpdate () {
// 确保函数只被执行一次
if (!isLateUpdate) {
Debug.Log ("Late Update");
isLateUpdate = true;
}
}
// 当对象变为不可用或非激活状态时此函数被调用
void OnDisable () {
Debug.Log ("On Disable");
}
// 当对象变为可用或激活状态时此函数被调用
void OnEnable () {
Debug.Log ("On Enable");
}
// 渲染和处理 GUI 事件时调用
void OnGUI () {
// 确保函数只被执行一次
if (!isOnGUI) {
Debug.Log ("On GUI");
isOnGUI = true;
}
}
}
运行结果如下图:
可以看出,基本行为和事件的发生顺序为:
- Awake()
- OnEnable()
- Start()
- FixedUpdate()
- Update()
- LateUpdate()
- OnGUI()
- OnDisable()
顺序满足各事件触发的条件。
FixedUpdate()、LateUpdate()和Update()的区别:
FixedUpdate()
处理 Rigidbody 时,需要用 FixedUpdate 代替 Update。例如: 给刚体加一个作用力时,你必须应用作用力在 FixedUpdate 里的固定帧,而不是 Update 中的帧(两者帧长不同)。
LateUpdate()
LateUpdate 是在所有 Update 函数调用后被调用。这可用于调整脚本执行顺序。例如: 当物体在 Update 里移动时,跟随物体的相机可以在 LateUpdate 里实现。
查找脚本手册,了解 GameObject,Transform,Component 对象
分别翻译官方对三个对象的描述(Description)
GameObject
GameObjects are the fundamental objects in Unity that represent characters, props and scenery.
游戏对象是Unity中基础的对象,它代表了角色、道具和场景。
Transform
The Transform component determines the Position, Rotation, and Scale of each object in the scene.
变换组件决定了场景中每个对象的位置、旋转角度和缩放比例。
Component
Components are the nuts & bolts of objects and behaviors in a game.
组件是游戏中对象和行为的枢纽。
描述下图中 table 对象(实体)的属性、table 的 Transform 的属性、 table 的部件
- table 对象(实体)的属性
- Name: 对象的名字
- Tag: 用于通过 Tag 名称来快速查找对象
- Layer: 可用于仅对某些特定的对象组投射光线、渲染或应用光照
- Static: 准备静态几何结构以用于自动批处理;计算遮挡剔除 (Occlusion Culling)
- table 的 Transform 的属性
- Position: X、Y 和 Z 坐标中变换的位置。(0, 0, 0)
- Rotation: 围绕 X、Y 和 Z 轴的旋转,以度计。(0, 0, 0)
- Scale: 沿 X、Y 和 Z 轴的缩放,“1” 是原始大小。(1, 1, 1)
- table 的部件
- Cube (Mesh Filter): 网格过滤器从资源中拿出网格并将其传递给网格渲染器 (Mesh Renderer) 用于屏幕渲染
- Box Collider: 箱体碰撞体 (Box Collider) 是基本立方体形碰撞基元
- Mesh Renderer: 网格渲染器 (Mesh Renderer) 从网格过滤器 (Mesh Filter) 获得几何结构,并根据物体的变换组件 (Transform) 定义的位置进行渲染
- Material: 材质用于将纹理置于游戏对象 (GameObject) 上
- table 对象(实体)的属性
用 UML 图描述 三者的关系(请使用 UMLet 14.1.1 stand-alone版本出图)
整理相关学习资料,编写简单代码验证以下技术的实现:
查找对象
1
2
3
4
5
6//通过名字查找:
public static GameObject Find(string name);
//通过标签查找单个对象:
public static GameObject FindWithTag(string tag);
//通过标签查找多个对象:
public static GameObject[] FindGameObjectsWithTag(string tag);添加子对象
1
public static GameObject CreatePrimitive(PrimitiveTypetype);
遍历对象树
1
2
3foreach (Transform child in transform) {
Debug.Log(child.gameObject.name);
}清除所有子对象
1
2
3foreach (Transform child in transform) {
Destroy(child.gameObject);
}
资源预设(Prefabs)与 对象克隆 (clone)
预设(Prefabs)有什么好处?
预设就是预制好的游戏对象,包含了完整的组件和属性,可看作是游戏对象的模板。利用预制能够批量实例化出具有相同属性的游戏对象。预设与实例之间是联系的,改变预设的属性能够更改所有与之关联的对象的属性。
预设与对象克隆 (clone or copy or Instantiate of Unity Object) 关系?
不同于预设,对象克隆只是对对象的复制,新对象与克隆本体之间没有关联,不会相互影响。
制作 table 预制,写一段代码将 table 预制资源实例化成游戏对象
1 | // C# Script |
效果图如下:
尝试解释组合模式(Composite Pattern / 一种设计模式)。使用 BroadcastMessage() 方法向子对象发送消息
组合模式将对象组合成树形结构,以表示 “部分整体” 的层次结构。这种模式使得用户能够以一致的方式处理单个对象及对象的组合。
父类对象方法:
1 | void Start () { |
子类对象方法:1
2
3void CallChildren () {
Debug.Log ("I'm here!");
}