1、简答题
-
解释 游戏对象(GameObjects) 和 资源(Assets)的区别与联系。
-
游戏对象是游戏中具有一定属性、参数、构件的一种对象,它可以是一个场景,一个角色,一个装备等。
-
资源指的是在游戏中使用到的模型、声音文件、贴图文件等等。
-
两者之间的联系:资源可以构成游戏对象,游戏对象也可以作为资源。
-
-
下载几个游戏案例,分别总结资源、对象组织的结构(指资源的目录组织结构与游戏对象树的层次结构)
游戏案例AngryBots- 资源的结构
项目中的各种资源按照Animations、Editor等等各种类别分别进行归类,每一类资源都放置在对应的子文件夹中。 - 对象组织的结构
每一个大的对象都是由若干个具体的小对象进行组合得到的,每一个小对象可以构成很多个不同的大对象。这种构成方法可以由大到小逐步构成一个复杂的游戏对象。
- 资源的结构
-
编写一个代码,使用 debug 语句来验证 MonoBehaviour 基本行为或事件触发的条件
基本行为包括 Awake() Start() Update() FixedUpdate() LateUpdate()
常用事件包括 OnGUI() OnDisable() OnEnable()
查找脚本手册,了解 GameObject,Transform,Component 对象- Awake:在载入Script的时候执行对应代码
- Start:在所有的Update之前被调用
- Update:固定每一帧进行调用
- FixedUpdate:间隔固定的时间进行一次执行,而不是依赖于帧数。
- LateUpdate:每一帧进行一次调用,它会在所有Update之后执行。
- Ongui:在每一次渲染或者操作GUI时执行调用。
- OnDisable:在行为被disable的时候进行调用。
- OnEnable:在行为被enable的时候进行调用。
可以看出调用了Awake、Enable、Start等之后,每一帧都进行了Update
最后停止执行的时候调用了Disable
执行代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FirstBeh : MonoBehaviour {
// Use this for initialization
void Start () {
Debug.Log("This Start!");
}
// Update is called once per frame
void Update () {
Debug.Log("This Update!");
}
void OnEnable () {
Debug.Log("This Enabled!");
}
void OnDisable () {
Debug.Log("This Disabled!");
}
void Awake(){
Debug.Log("This Awake!");
}
void FixedUpdate()
{
Debug.Log("This FixedUpdate!");
}
void LateUpdate()
{
Debug.Log("This LateUpdate!");
}
}
-
查找脚本手册,了解 GameObject,Transform,Component 对象
-
分别翻译官方对三个对象的描述(Description)
GameObject:所有游戏元素的基础。
Transform:对游戏对象的移动、旋转、放缩
Component:和游戏对象相联系的基础类 -
描述下图中 table 对象(实体)的属性、table 的 Transform 的属性、 table 的部件
ActiveSelf:定义对象的名称和活动状态。
Transform:定义对象的位置,角度,放缩
BoxCollider:调整坐标系的位置和放缩
Component:对象的相关组件
-
-
本题目要求是把可视化图形编程界面与 Unity API 对应起来,当你在 Inspector 面板上每一个内容,应该知道对应 API。
例如:table 的对象是 GameObject,第一个选择框是 activeSelf 属性。
用 UML 图描述 三者的关系(请使用 UMLet 14.1.1 stand-alone版本出图)
-
整理相关学习资料,编写简单代码验证以下技术的实现:
查找对象
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Scr : MonoBehaviour {
// Use this for initialization
void Start () {
var obj = GameObject.Find("Table");
Debug.Log(obj);
}
// Update is called once per frame
void Update () {
}
}
通过GameObject.Find可以查找到具有对应ID的图像。
添加子对象
通过CreatePrimitive函数,新建一个特定类型的对象。使用新建对象的transform.parent,修改对象的parent关系。
遍历对象树
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Scr : MonoBehaviour {
// Use this for initialization
void Start () {
var obj = GameObject.Find("Table");
Debug.Log(obj);
GameObject subele = GameObject.CreatePrimitive(PrimitiveType.Cube);
subele.name = "sub";
subele.transform.position = new Vector3(0,3,0);
subele.transform.parent = obj.transform;
var trans = obj.transform;
foreach(Transform sub in trans)
{
Debug.Log(sub.name);
}
}
// Update is called once per frame
void Update () {
}
}
使用forech遍历子对象
清除所有子对象
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Scr : MonoBehaviour {
// Use this for initialization
void Start () {
var obj = GameObject.Find("Table");
Debug.Log(obj);
GameObject subele = GameObject.CreatePrimitive(PrimitiveType.Cube);
subele.name = "sub";
subele.transform.position = new Vector3(0,3,0);
subele.transform.parent = obj.transform;
var trans = obj.transform;
foreach(Transform sub in trans)
{
Debug.Log(sub.name);
Destroy(sub.gameObject);
}
}
// Update is called once per frame
void Update () {
}
}
-
资源预设(Prefabs)与 对象克隆 (clone)
- 预设(Prefabs)有什么好处?
预设将已经设计好的对象进行封装,在后续的设计开发过程中直接导入项目当中,更加贴合面向对象的设计要求,设计过程更加便捷。 - 预设与对象克隆 (clone or copy or Instantiate of Unity Object) 关系?
克隆是指将已经存在的对象进行复制,复制的对象也可以是预设。预设可以为克隆提供一个非常好的模板。
- 预设(Prefabs)有什么好处?
-
制作 table 预制,写一段代码将 table 预制资源实例化成游戏对象
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LoadBeh : MonoBehaviour {
public Transform res;
// Use this for initialization
void Start () {
// Load Resources
Object table = Resources.Load("Table");
GameObject newobj = Instantiate(table) as GameObject;
newobj.transform.position = new Vector3 (0, Random.Range (-5, 5), 0);
newobj.transform.parent = this.transform;
}
}
通过load对应的预设元素,进行复制之后重新调整位置。
- 井字棋
通过利用GUI事件和创建GUI Lebel和Button的方法,可以完成本次任务。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GG : MonoBehaviour {
int[, ] board = new int[3, 3];
int turn;
int remain = 9;
int judge () {
if (board[1, 1] == board[1, 0] && board[1, 1] == board[1, 2] && 0 != board[1, 1]) return board[1, 1];
if (board[1, 1] == board[0, 1] && board[1, 1] == board[2, 1] && 0 != board[1, 1]) return board[1, 1];
if (board[1, 1] == board[0, 0] && board[1, 1] == board[2, 2] && 0 != board[1, 1]) return board[1, 1];
if (board[1, 1] == board[2, 0] && board[1, 1] == board[0, 2] && 0 != board[1, 1]) return board[1, 1];
if (board[0, 0] == board[1, 0] && board[1, 0] == board[2, 0] && 0 != board[1, 0]) return board[1, 0];
if (board[0, 0] == board[0, 1] && board[0, 1] == board[0, 2] && 0 != board[0, 1]) return board[0, 1];
if (board[2, 2] == board[1, 2] && board[1, 2] == board[0, 2] && 0 != board[1, 2]) return board[1, 2];
if (board[2, 2] == board[2, 1] && board[2, 1] == board[2, 0] && 0 != board[2, 1]) return board[2, 1];
if (remain == 0) return 2;
return 0;
}
// Use this for initialization
void Start () {
reset ();
}
void reset () {
turn = 1;
int i, j;
for (i = 0; i <= 2; ++i)
for (j = 0; j <= 2; ++j)
board[i, j] = 0;
remain = 9;
}
void showRes () {
if (judge () == 1)
GUI.Label (new Rect (420 , 20, 100, 80), "O is winner!");
else if (judge () == -1)
GUI.Label (new Rect (420 , 20, 100, 80), "X is winner!");
else if (judge () == 2)
GUI.Label (new Rect (420 , 20, 100, 80), "Draw!");
else GUI.Label (new Rect (420 , 20, 100, 80), "Running!");
}
void OnGUI () {
if (GUI.Button (new Rect (400 , 450, 100, 80), "Reset")) {
Start ();
}
showRes ();
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++) {
if (board[i, j] == 1) GUI.Button (new Rect (i * 100 + 300, j * 100 + 100, 100, 100), "O");
if (board[i, j] == -1) GUI.Button (new Rect (i * 100 + 300, j * 100 + 100, 100, 100), "X");
// if (board[i, j] == 0) GUI.Button (new Rect (i * 100 + 400, j * 100 + 80, 100, 100), "");
if (GUI.Button (new Rect (i * 100 + 300, j * 100+ 100, 100, 100), "")) {
if (judge () == 0 && board[i, j] == 0) {
board[i, j] = turn;
remain--;
turn = -turn;
showRes ();
}
}
}
}
// Update is called once per frame
void Update () {
}
}