离散仿真引擎基础

Mar 25, 2018


解释 游戏对象(GameObjects) 和 资源(Assets)的区别与联系

游戏对象(GameObjects)是场景中的实体 资源(Assets)是项目的素材

游戏对象可作为资源;资源可以添加到游戏对象的组件中,也可以直接创建为新的游戏对象


下载几个游戏案例,分别总结资源、对象组织的结构(指资源的目录组织结构与游戏对象树的层次结构)

资源以文件夹形式存储,实体之间为继承关系


编写一个代码,使用 debug 语句来验证 MonoBehaviour 基本行为或事件触发的条件

  • 基本行为包括 Awake() Start() Update() FixedUpdate() LateUpdate()
  • 常用事件包括 OnGUI() OnDisable() OnEnable()
1
void Awake () { Debug.Log ("Awake"); }

函数调用顺序: Awake –> OnEnable –> Start –> Update –> FixedUpdate –> LateUpdate –> OnGUI – > OnDisable

  1. Awake: 用于在游戏开始之前初始化变量或游戏状态。
  2. OnEnable: 当物体被创建时将被调用。
  3. Start:仅在Update函数第一次被调用前调用。
  4. Update:正常帧更新,用于更新逻辑。
  5. FixedUpdate:固定帧更新。
  6. LateUpdate:在所有Update函数调用后被调用。
  7. OnGUI:在渲染和处理GUI事件时调用。
  8. OnDisable:当物体被销毁时将被调用,并且可用于任意清理代码。

查找脚本手册,了解 GameObject,Transform,Component 对象

  • 分别翻译官方对三个对象的描述(Description)

游戏物体(GameObject):Unity场景里面所有实体的基类。

变换(Transform):物体的位置、旋转和缩放。

组件(Component):一切附加到游戏物体的基类。

  • 描述下图中 table 对象(实体)的属性、table 的 Transform 的属性、 table 的部件

Image text

table 对象的属性依次是activeSelf、isStatic、tag、layer

Transform 的属性依次是position、rotation、Scale

table 的部件依次是Tranform、Mesh Filter、Box Collider、Mesh Renderer

  • 用 UML 图描述 三者的关系(请使用 UMLet 14.1.1 stand-alone版本出图)

Image text


整理相关学习资料,编写简单代码验证以下技术的实现

  • 查找对象
1
GameObject hand = GameObject.Find("Hand");
  • 添加子对象
1
GameObject plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
  • 遍历对象树
1
foreach (Transform child in transform) {}
  • 清除所有子对象
1
2
3
foreach (Transform child in transform) {
    GameObject.Destroy(child.gameObject);
}

资源预设(Prefabs)与 对象克隆 (clone)

  • 预设(Prefabs)有什么好处?

    对大量存在的实体可以批量创建

  • 预设与对象克隆 (clone or copy or Instantiate of Unity Object) 关系?

    预设创建的实体会根据预设的变化而变化,而克隆的实体不会因为原实体的变化而变化

  • 制作 table 预制,写一段代码将 table 预制资源实例化成游戏对象
1
GameObject instance = (GameObject)Instantiate(MyTable, transform.position, transform.rotation);

尝试解释组合模式(Composite Pattern / 一种设计模式)。使用 BroadcastMessage() 方法

组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。 这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。

  • 向子对象发送消息

父类

1
void Start () { this.BroadcastMessage("transferMsg"); }

子类

1
void transferMsg() { Debug.Log("Halo"); }

井字棋

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Chess : MonoBehaviour {

	int turn; //记录当前是第几轮
	int [,] record = new int[3,3]; //用来存储棋盘信息

	//初始化、重置信息
	void Clear() {
		turn = 1;
		for (int i = 0; i < 3; i++) {  
			for (int j = 0; j < 3; j++) {  
				record[i,j] = 0;  
			}  
		}
	}

	//检查棋盘状况,判断胜负情况
	int Check() {
		
		if (turn < 3) //若当前还没到第三轮,直接return
			return 0;
		
		int state;
		if (record[1,1] != 0) { //若棋盘中心为0,判断以其为中心的四条线
			state = record [1,1];
			if ((record [0,0] == state && record [2,2] == state) || (record [0,2] == state && record [2,0] == state))
				return state;
			if ((record [0,1] == state && record [2,1] == state) || (record [1,0] == state && record [1,2] == state))
				return state;
		}

		state = record [0,0]; //判断最上方、最左方两条线
		if ((record [0,1] == state && record [0,2] == state) || (record [1,0] == state && record [2,0] == state))
			return state;
		
		state = record [2,2]; //判断最下方、最右方两条线
		if ((record [2,0] == state && record [2,1] == state) || (record [1,2] == state && record [0,2] == state))
			return state;
		
		return 0;
	}

	// Use this for initialization
	void Start () {
		Clear ();
	}

	void OnGUI () {
		if(GUI.Button(new Rect(400,50,150,50),"RESTART")) //判断RESTART按钮点击情况
			Clear();

		int state = Check (); //获取检查棋盘的信息

		if (turn > 9 && state == 0) //若当前轮数大于9且未分出胜负,则输出Tied
			GUI.Label (new Rect (400, 105, 50, 50), "Tied!");
		else if (state == 1) {
			GUI.Label (new Rect (400, 105, 50, 50), "O Win!");
			state = 1; //若以分出胜负,要改变state的值,在下方要用到
		} else if (state == 2) {
			GUI.Label (new Rect (400, 105, 50, 50), "X Win!");
			state = 2;
		}
		
		for(int i = 0 ; i < 3 ; i++) //刷新棋盘
			for (int j = 0; j < 3; j++) {
				
				if (record[i,j] == 1)
					GUI.Button (new Rect (400 + 50 * i, 130 + 50 * j, 50, 50), "O");
				else if (record[i,j] == 2)
					GUI.Button (new Rect (400 + 50 * i, 130 + 50 * j, 50, 50), "X");
				else if(GUI.Button(new Rect(400+50*i,130+50*j,50,50),""))
					if (state == 0) {
						if (turn % 2 == 0)
							record [i, j] = 1;
						else
							record [i, j] = 2;
						turn ++;
					}
			}
	}

}

参考资料