1、简答题
1-1.解释游戏对象和资源的区别和联系
游戏对象(GameObjects)是在游戏中真实存在的可操作的对象(从角色、可收集物品到光源、摄像机和特效都是游戏对象),它们本身无法执行任何操作,需要人工提供属性才能成为角色、环境或特效;
资源(Assets)则是可以在项目中使用的任何项,可以是外部的模型、音频文件和图像,也可以是内部创建的资源类型,它们对游戏对象进行修饰。
联系与区别:资源可以作为模板,实例化成为具体的游戏对象,也可以作为游戏对象的某种属性被游戏对象使用。
1-2.下载几个游戏案例,分别总结资源、对象组织的结构
(资源的目录组织结构与游戏对象树的层次结构)
①motion:
从上面两个图可以看出,
资源的目录组织结构:根目录,根目录下有材料文件夹、预制文件夹、Script文件夹和纹理文件夹。
游戏树的层次结构:并行的摄像机、光源和Main空游戏对象和sunset游戏对象,sunset里面包含earth,earth里面又包含moon。
②Roll-a-ball
从上面的图可以看出,
资源的目录组织结构:根目录,根目录下有资源文件夹、预设文件夹和Script文件夹
游戏对象树的层次结构:第一层有光源、地面、玩家、主摄像机、墙、食物(pick ups)、文字面板和事件系统。其中墙的游戏对象中又包含东南西北四面墙,食物游戏对象里面包含12个子对象,文字面板中包含计数板和胜利文字面板。
1-3编写一个代码,使用debug语句来验证MonoBehaviour基本行为或事件触发条件。
- 基本行为包括:Awake() Start() Update() FixedUpdate() LateUpdate()
- 常用事件包括:OnGUI() OnDisable() OnEnable()
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class test : MonoBehaviour
{
void Awake()
{
Debug.Log("Awake");
}
void Start()
{
Debug.Log("Start");
}
void Update()
{
Debug.Log("Update");
}
void FixUpdate()
{
Debug.Log("FixUpdate");
}
void LateUpdate()
{
Debug.Log("LateUpdate");
}
void OnGUI()
{
Debug.Log("OnGUI");
}
void OnDisable()
{
Debug.Log("OnDisable");
}
void OnEnable()
{
Debug.Log("OnEnable");
}
}
在控制台的输出如下:
分析发现:
- Awake:当一个脚本被载入时调用一次
- Start:在Awake后,所有update函数前调用一次
- Update:进入游戏循环后,每一帧调用遗传
- FixUpdate:在游戏循环中重复调用
- LateUpdate:所有的Update函数调用完后调用
- OnGUI:在渲染过程中,场景渲染之后调用
- OnDisable:某物体被禁用时调用
- OnEnable:当取消禁用时被调用。
1-4查找脚本手册,了解GameObject,Transform,Component对象
(1)分别翻译官方对三个对象的描述(Description)
- GameObject:在unity的场景中所有实体的基类。
- Transform: 物体的位置、旋转和缩放
- Component:一切附加到游戏物体的基类
(2)描述下图中table对象(实体)的属性、Transform的属性和table的部件
- table的对象是GameObject;
- table的Transform属性包括坐标位置(原点),旋转位置(未设置,均为0)和缩放属性(未更改,是x、y、z都为1的立方体);
- table共有5个部件,第一个是activeSelf属性,第二个是Transform属性,第三个是MeshFilter属性,第四个是BoxCollider属性,第五个是MeshRenderer属性。
(3)用UML图描述三者的关系
1-5资源预设与对象克隆
(1)预设(Prefabs)有什么好处?
1、可以快速、方便的创建大量可以重复利用的资源;
2、可以在程序运行时来执行实例化操作,提高程序运行效率,节省内存空间。
(2)预设与对象克隆关系?
相同点:两者都能复制相同的游戏对象;
不同点:预制可以大量批量复制对象,而克隆只能用来复制少量的对象;预制是一个设计好的程序,而克隆则是对已经添加在视图中的游戏对象进行复制。
(3)制作table预制,写一段代码将table预制资源实例化成游戏对象
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class tableperfabs : MonoBehaviour
{
public Transform res;
void Start()
{
GameObject newobj = Instantiate<Transform> (res, this.transform).gameObject;
newobj.transform.position = new Vector3(0, Random.Range(-5,5), 0);
}
}
编写完脚本后,将脚本添加到相应的部件中,然后将cube拖放至res对应的位置,运行游戏,便能得到table的游戏对象了。
2、编程实践,小游戏
- 游戏内容:井字棋或贷款计算器或简单计算器
- 技术限制:仅允许使用IMGUI构建UI
- 作业目的:
- 了解OnGUI()事件,提高debug能力
- 提升阅读API文档能力
井字棋游戏
代码实现
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class game : MonoBehaviour
{
private int[,] chess = new int[3,3];
private int turn = 0; //0为O,1为X
private int blanksize = 9; //空白格数量
private int size = 50;
void Start()
{
restart();
}
void restart()
{
blanksize = 9;
turn = 0;
for(int i=0 ; i<3 ; i++){
for(int j=0 ; j<3 ; j++){
chess[i,j] = 0;
}
}
}
int getWin()
{
for(int i=0 ; i<3 ; i++){
if(chess[i,0]==chess[i,1] && chess[i,1]==chess[i,2])
return chess[i,0];
if(chess[0,i]==chess[1,i] && chess[1,i]==chess[2,i])
return chess[0,i];
}
if(chess[0,0]==chess[1,1] && chess[1,1]==chess[2,2])
return chess[0,0];
if(chess[0,2]==chess[1,1] && chess[1,1]==chess[2,0])
return chess[0,2];
if(blanksize==0)
return 3;
return 0;
}
void OnGUI()
{
GUI.skin.button.fontSize = 20;
GUI.skin.label.fontSize = 20;
if(GUI.Button(new Rect(250, 250, 150, 50), "Restart")){
restart();
}
int result = getWin();
if(result == 1)
GUI.Label(new Rect(300, 50, 100, 50), "O wins!");
else if(result == 2)
GUI.Label(new Rect(300, 50, 100, 50), "X wins!");
else if(result == 3)
GUI.Label(new Rect(300, 50, 100, 50), "Draw!");
for(int i=0 ; i<3 ; i++){
for(int j=0 ; j<3 ; j++){
if(chess[i,j] == 1)
GUI.Button(new Rect(size*i+250, size*j+100, size, size), "O");
if(chess[i,j] == 2)
GUI.Button(new Rect(size*i+250, size*j+100, size, size), "X");
if(GUI.Button(new Rect(size*i+250, size*j+100, size, size), "")){
if(result == 0){
if(turn == 0){
chess[i,j] = 1;
}
else
chess[i,j] = 2;
turn = 1- turn;
blanksize--;
}
}
}
}
}
}