一、简答题
1. 解释游戏对象(GameObjects)和资源(Assets)的区别与联系
- 游戏对象(GameObjects)
首先我们我们来看一下Unity官方是怎么描述游戏对象的:
游戏对象是 Unity 中的基础对象,表示角色、道具和景物。它们本身并没有取得多大作为,但它们充当组件的容器,而组件可实现功能。为了向游戏对象提供成为光源、树或摄像机所需的属性,需要向游戏对象添加组件。根据要创建的对象类型,可以向游戏对象添加不同的组件组合。
Unity 拥有许多不同的内置组件类型,而且还可以使用 Unity Scripting API 来创建自己的组件。例如,通过将光源组件附加到游戏对象来创建光源对象。游戏中的每个对象(从角色和可收集物品到光源、摄像机和特效)都是游戏对象。但是,游戏对象本身无法执行任何操作;您需要向游戏对象提供属性,然后游戏对象才能成为角色、环境或特效。
- 资源(Assets)
我们再来看一下Unity官方是怎么描述资源的:
资源包集合了来自 Unity 项目或项目元素的文件和数据,Unity 将它们压缩并存储在一个扩展名为 .unitypackage 的文件中。与 zip 文件一样,资源包在解压缩后保持其原始目录结构,其中还包括资源的元数据(例如导入设置和指向其他资源的链接)。
- 区别与联系
从定义我们可以看出,资源是存储在Unity项目的Assets文件夹中的磁盘文件。纹理、3D模型以及音频等等都属于常见的资源。而对象是用于描述资源的特定实例的序列化数据集合。它可以是由Unity引擎所使用的任何类型的资源,例如上面所提到的纹理、3D模型以及音频。
2. 下载几个游戏案例,分别总结资源、对象组织的结构(指资源的目录组织结构与游戏对象树的层次结构)
资源的结构
由样例可以发现,project文件夹里分为Assets文件夹和Packages文件夹,Assets文件夹里又细分为Scenes文件夹、Scripts文件夹和Surface文件夹,这样可以根据资源文件的不同类型放入不同的文件夹中,便于资源的整理和利用
游戏对象的结构
由样例可以发现,游戏对象可以分为各种实体、摄像机、光源等环境的设置、玩家等等
3. 编写一个代码,使用debug语句来验证MonoBehaviour基本行为或事件触发的条件
代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class new : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
Debug.Log("Start run!");
}
// Update is called once per frame
void Update()
{
Debug.Log("Update run!");
}
void Awake()
{
Debug.Log("Awake run!");
}
void FixedUpdate()
{
Debug.Log("FixedUpdate run!");
}
void OnGUI()
{
Debug.Log("OnGUI run!");
}
void OnDisable()
{
Debug.Log("OnDisable run!");
}
void OnEnable()
{
Debug.Log("OnEnable run!");
}
}
打开新项目,将脚本加入到Main Camera中,运行项目,控制台输出如下:
从运行结果可以看出,MonoBehaviour基本行为或事件触发的条件如下:
- Start():在首次调用任何 Update 方法之前启用脚本时,在帧上调用 Start。
- Update():如果启用了 MonoBehaviour,则每帧调用 Update。
- FixedUpdate():MonoBehaviour.FixedUpdate 具有物理系统的频率;每个固定帧率帧调用该函数。
- LateUpdate():如果启用了 Behaviour,则每帧调用 LateUpdate。
- OnGUI():系统调用 OnGUI 来渲染和处理 GUI 事件。
- OnDisable():该函数在行为被禁用时调用。
- OnEnable():该函数在对象变为启用和激活状态时调用。
4. 查找脚本手册,了解GameObject,Tranform,Component对象
首先我们来看一下官方对于该三个对象的描述:
- GameObject:Unity 场景中所有实体的基类。
- Tranform:对象的位置、旋转和缩放。
- Component:附加到 GameObject 的所有内容的基本类。
(图呢???)
5. 资源预设(Prefabs)与对象克隆(clone)
首先我们来思考这样一个问题,即预设(Prefabs)有什么好处?
在我们开发一些功能的时候,可以将一些能够复用的对象制作成预设件,可以将预设件存放到 Resources 目录之下,通过动态加载的方式加载到场景中并进行实例化。这样当我们需要大量使用某一游戏物体时,就避免重复的劳动,让我们开发游戏更加快捷。
如此看来,预制和克隆似乎是一致的,那么它们有什么区别呢?
答案就是克隆是将已经存在的游戏对象,或者是资源当中的预设进行复制。克隆可以是对已经添加在视图当中的游戏对象进行复制,也可以是对资源当中,我们提前预设好的模板进行克隆。因此,预设一般来说是克隆的一个基础步骤,在预设之后,就可以在资源当中随心所欲地为自己想要的对象进行克隆了。
(table在哪??写什么代码??)
二、编程实践——井字棋
- 游戏内容:井字棋
- 技术限制:仅使用IMGUI构建UI
代码实现如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Chess_1 : MonoBehaviour
{
GUIStyle myStyle;
private int turn = 1;
private int num = 0;
private int[,] matrix = new int[3,3];
int middle=Screen.width / 2;
void reset(){
turn = 1;
num = 0;
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
matrix[i,j]=0;
}
}
print("game reseted.");
}
int check(){
for(int i=0;i<3;i++){
//列的检测
if(matrix[i,0]!=0 && (matrix[i,0]==matrix[i,1] && matrix[i,0]==matrix[i,2])){
return matrix[i,0];
}
//行的检测
if(matrix[0,i]!=0 && (matrix[0,i]==matrix[1,i] && matrix[0,i]==matrix[2,i])){
return matrix[0,i];
}
}
//对角线检测
if(matrix[0,0]!=0&&(matrix[0,0]==matrix[1,1]&&matrix[0,0]==matrix[2,2])){
return matrix[0,0];
}
if(matrix[0,2]!=0&&(matrix[0,2]==matrix[1,1]&&matrix[0,2]==matrix[2,0])){
return matrix[0,2];
}
if(num<9) return 0;
return 3;
}
void result(int res){
switch(res){
case 0:
if(turn == 1)
GUI.Box(new Rect(middle-45,55,100,35),"O's turn");
else if(turn == 2)
GUI.Box(new Rect(middle-45,55,100,35),"X's turn");
break;
case 1:
GUI.Box(new Rect(middle-45,55,100,35),"0 is Win!");
break;
case 2:
GUI.Box(new Rect(middle-45,55,100,35),"X is Win!");
break;
case 3:
GUI.Box(new Rect(middle-45,55,100,35),"Draw!");
break;
}
}
void click(int i,int j){
matrix[i,j]=turn;
num++;
turn = (turn == 1) ? 2 : 1;
}
void OnGUI(){
//游戏背景的box
GUI.Box(new Rect(middle-120,30,252,330),"tic-tac-toe");
//restart按钮
if(GUI.Button(new Rect(middle-35,95,75,30),"Restart")){
reset();
}
int res=check();
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if(matrix[i,j]==1){
GUI.Button(new Rect(middle-120+i*84,135+j*70,84,70),"O");
}
if(matrix[i,j]==2){
GUI.Button(new Rect(middle-120+i*84,135+j*70,84,70),"X");
}
if(GUI.Button(new Rect(middle-120+i*84,135+j*70,84,70),"")){
click(i,j);
}
}
result(res);
}
}
}
- 首先是完善reset()函数,以及判断是否有三连的check()函数
- result()函数接收check()函数的返回值,根据返回值来对局面进行判断,再通过OnGUI进行的渲染
- click()函数负责点击行为的逻辑
将写好的C#脚本添加进Main Camera中运行,游戏效果如下所示:
三、参考资料
[1]. Unity官方手册
[2]. 3d学习笔记(一)——游戏对象与资源